Merge branch 'legislation-module-stable' into sandbox-html
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
//= require markdown_editor
|
||||
//= require cocoon
|
||||
//= require allegations
|
||||
//= require legislation_questions
|
||||
//= require custom
|
||||
|
||||
var initialize_modules = function() {
|
||||
@@ -74,6 +75,7 @@ var initialize_modules = function() {
|
||||
App.SocialShare.initialize();
|
||||
App.MarkdownEditor.initialize();
|
||||
App.Allegations.initialize();
|
||||
App.LegislationQuestions.initialize();
|
||||
};
|
||||
|
||||
$(function(){
|
||||
|
||||
8
app/assets/javascripts/legislation_questions.js.coffee
Normal file
8
app/assets/javascripts/legislation_questions.js.coffee
Normal file
@@ -0,0 +1,8 @@
|
||||
App.LegislationQuestions =
|
||||
|
||||
initialize: ->
|
||||
$('form#new_legislation_answer input.button').hide()
|
||||
$('form#new_legislation_answer input[type=radio]').on
|
||||
click: ->
|
||||
$('form#new_legislation_answer').submit()
|
||||
|
||||
@@ -13,4 +13,5 @@ App.Votes =
|
||||
initialize: ->
|
||||
App.Votes.hoverize "div.votes"
|
||||
App.Votes.hoverize "div.supports"
|
||||
App.Votes.hoverize "div.debate-questions"
|
||||
false
|
||||
|
||||
@@ -901,16 +901,12 @@ img.avatar, img.admin-avatar, img.moderator-avatar, img.initialjs-avatar {
|
||||
}
|
||||
|
||||
.author-deleted, .user-deleted {
|
||||
background-color: rgba(255,255,255,.5);
|
||||
color: rgba(0,0,0,.4);
|
||||
font-size: rem-calc(40);
|
||||
left: 11px;
|
||||
position: absolute;
|
||||
top: 72px;
|
||||
}
|
||||
|
||||
.user-deleted {
|
||||
top: -4px;
|
||||
display: inline-block;
|
||||
font-size: rem-calc(32);
|
||||
line-height: rem-calc(32);
|
||||
height: rem-calc(32);
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
.user-permissions {
|
||||
@@ -1069,10 +1065,6 @@ img.avatar, img.admin-avatar, img.moderator-avatar, img.initialjs-avatar {
|
||||
background: #C0392B;
|
||||
}
|
||||
|
||||
.is-deleted {
|
||||
background: #E7E7E7;
|
||||
}
|
||||
|
||||
.level-1 {
|
||||
background: #1ABC9C;
|
||||
}
|
||||
@@ -1601,7 +1593,10 @@ table {
|
||||
}
|
||||
|
||||
.comment-body {
|
||||
margin-left: rem-calc(42);
|
||||
|
||||
img {
|
||||
margin-right: $line-height/2;
|
||||
}
|
||||
|
||||
.reply {
|
||||
background: white;
|
||||
@@ -1609,20 +1604,28 @@ table {
|
||||
border-left: 0;
|
||||
border-right: 0;
|
||||
font-size: $small-font-size;
|
||||
margin: rem-calc(6) 0;
|
||||
padding: rem-calc(6);
|
||||
margin: $line-height/4 0;
|
||||
padding: $line-height/4;
|
||||
position: relative;
|
||||
|
||||
a.relative, [class^="icon-arrow"] {
|
||||
padding-left: $line-height/2;
|
||||
}
|
||||
|
||||
[class^="icon-arrow"] {
|
||||
font-size: rem-calc(18);
|
||||
font-size: $base-font-size;
|
||||
left: -20px;
|
||||
position: absolute;
|
||||
top: 0;
|
||||
top: -1px;
|
||||
}
|
||||
|
||||
.divider {
|
||||
color: $text-light;
|
||||
}
|
||||
|
||||
form {
|
||||
margin-top: $line-height/2;
|
||||
}
|
||||
}
|
||||
|
||||
.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 {
|
||||
border-left: 1px dashed $border;
|
||||
margin-left: rem-calc(42);
|
||||
padding-left: $line-height/4;
|
||||
|
||||
@media only screen and (max-width: 40em) {
|
||||
margin-left: rem-calc(16);
|
||||
}
|
||||
display: inline-block;
|
||||
margin-left: rem-calc(16);
|
||||
padding-left: rem-calc(8);
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.comment-info {
|
||||
color: $text-medium;
|
||||
display: inline-block;
|
||||
font-size: $small-font-size;
|
||||
margin-top: $line-height/4;
|
||||
vertical-align: middle;
|
||||
line-height: rem-calc(32); // Same as avatar height
|
||||
|
||||
span.user-name {
|
||||
color: $text;
|
||||
@@ -1703,6 +1698,11 @@ table {
|
||||
}
|
||||
}
|
||||
|
||||
.comment-form {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
// 16. Flags
|
||||
// ---------
|
||||
|
||||
|
||||
@@ -293,6 +293,7 @@
|
||||
}
|
||||
|
||||
.debate-questions {
|
||||
position: relative;
|
||||
list-style: none;
|
||||
|
||||
.control {
|
||||
|
||||
@@ -326,9 +326,13 @@
|
||||
clear: both;
|
||||
color: $text-medium;
|
||||
font-size: $small-font-size;
|
||||
min-height: $line-height*2;
|
||||
margin-bottom: $line-height/2;
|
||||
position: relative;
|
||||
|
||||
span {
|
||||
line-height: rem-calc(32); // Same as avatar height
|
||||
}
|
||||
|
||||
a {
|
||||
color: $text-medium;
|
||||
}
|
||||
@@ -338,15 +342,6 @@
|
||||
line-height: $line-height;
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
.author-deleted {
|
||||
left: 0;
|
||||
top: 4px;
|
||||
}
|
||||
|
||||
.author.deleted {
|
||||
margin-left: rem-calc(48);
|
||||
}
|
||||
}
|
||||
|
||||
.debate-description, .proposal-description {
|
||||
@@ -371,9 +366,9 @@
|
||||
}
|
||||
|
||||
.author-photo {
|
||||
line-height: $line-height*2;
|
||||
line-height: rem-calc(32);
|
||||
margin-right: rem-calc(6);
|
||||
vertical-align: middle;
|
||||
vertical-align: top;
|
||||
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
|
||||
41
app/controllers/legislation/answers_controller.rb
Normal file
41
app/controllers/legislation/answers_controller.rb
Normal file
@@ -0,0 +1,41 @@
|
||||
class Legislation::AnswersController < Legislation::BaseController
|
||||
before_action :authenticate_user!
|
||||
before_action :verify_resident!
|
||||
|
||||
load_and_authorize_resource :process
|
||||
load_and_authorize_resource :question, through: :process
|
||||
load_and_authorize_resource :answer, through: :question
|
||||
|
||||
respond_to :html, :js
|
||||
|
||||
def create
|
||||
if @process.open_phase?(:debate)
|
||||
@answer.user = current_user
|
||||
@answer.save
|
||||
track_event
|
||||
respond_to do |format|
|
||||
format.js
|
||||
format.html { redirect_to legislation_process_question_path(@process, @question) }
|
||||
end
|
||||
else
|
||||
respond_to do |format|
|
||||
format.js
|
||||
format.html { redirect_to legislation_process_question_path(@process, @question), alert: t('legislation.questions.participation.phase_not_open') }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
def answer_params
|
||||
params.require(:legislation_answer).permit(
|
||||
:legislation_question_option_id,
|
||||
)
|
||||
end
|
||||
|
||||
def track_event
|
||||
ahoy.track "legislation_answer_created".to_sym,
|
||||
"legislation_answer_id": @answer.id,
|
||||
"legislation_question_option_id": @answer.legislation_question_option_id,
|
||||
"legislation_question_id": @answer.legislation_question_id
|
||||
end
|
||||
end
|
||||
@@ -8,5 +8,6 @@ class Legislation::QuestionsController < Legislation::BaseController
|
||||
@commentable = @question
|
||||
@comment_tree = CommentTree.new(@commentable, params[:page], @current_order)
|
||||
set_comment_flags(@comment_tree.comments)
|
||||
@answer = @question.answer_for_user(current_user) || Legislation::Answer.new
|
||||
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
|
||||
@@ -1,5 +1,5 @@
|
||||
class ApplicationMailer < ActionMailer::Base
|
||||
helper :settings
|
||||
default from: "Consul <no-reply@consul.es>"
|
||||
default from: "#{Setting['mailer_from_name']} <#{Setting['mailer_from_address']}>"
|
||||
layout 'mailer'
|
||||
end
|
||||
|
||||
@@ -14,6 +14,7 @@ module Abilities
|
||||
can [:read, :draft_publication, :allegations, :final_version_publication], Legislation::Process
|
||||
can [:read], Legislation::DraftVersion
|
||||
can [:read], Legislation::Question
|
||||
can [:create], Legislation::Answer
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
9
app/models/legislation/answer.rb
Normal file
9
app/models/legislation/answer.rb
Normal file
@@ -0,0 +1,9 @@
|
||||
class Legislation::Answer < ActiveRecord::Base
|
||||
belongs_to :question, class_name: 'Legislation::Question', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :answers, counter_cache: true
|
||||
belongs_to :question_option, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_option_id', dependent: :destroy, inverse_of: :answers, counter_cache: true
|
||||
belongs_to :user, dependent: :destroy, inverse_of: :legislation_answers
|
||||
|
||||
validates :question, presence: true, uniqueness: { scope: :user_id}
|
||||
validates :question_option, presence: true
|
||||
validates :user, presence: true
|
||||
end
|
||||
@@ -2,9 +2,9 @@ class Legislation::Process < ActiveRecord::Base
|
||||
acts_as_paranoid column: :hidden_at
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
has_many :draft_versions, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id'
|
||||
has_many :draft_versions, -> { order(:id) }, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id'
|
||||
has_one :final_draft_version, -> { where final_version: true }, class_name: 'Legislation::DraftVersion', foreign_key: 'legislation_process_id'
|
||||
has_many :questions, class_name: 'Legislation::Question', foreign_key: 'legislation_process_id'
|
||||
has_many :questions, -> { order(:id) }, class_name: 'Legislation::Question', foreign_key: 'legislation_process_id'
|
||||
|
||||
validates :title, presence: true
|
||||
validates :description, presence: true
|
||||
|
||||
@@ -5,7 +5,8 @@ class Legislation::Question < ActiveRecord::Base
|
||||
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
|
||||
belongs_to :process, class_name: 'Legislation::Process', foreign_key: 'legislation_process_id'
|
||||
|
||||
has_many :question_options, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
|
||||
has_many :question_options, -> { order(:id) }, class_name: 'Legislation::QuestionOption', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
|
||||
has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
|
||||
has_many :comments, as: :commentable
|
||||
|
||||
accepts_nested_attributes_for :question_options, :reject_if => proc { |attributes| attributes[:value].blank? }, allow_destroy: true
|
||||
@@ -16,4 +17,8 @@ class Legislation::Question < ActiveRecord::Base
|
||||
def next_question_id
|
||||
@next_question_id ||= process.questions.where("id > ?", id).order('id ASC').limit(1).pluck(:id).first
|
||||
end
|
||||
|
||||
def answer_for_user(user)
|
||||
answers.where(user: user).first
|
||||
end
|
||||
end
|
||||
|
||||
@@ -3,6 +3,7 @@ class Legislation::QuestionOption < ActiveRecord::Base
|
||||
include ActsAsParanoidAliases
|
||||
|
||||
belongs_to :question, class_name: 'Legislation::Question', foreign_key: 'legislation_question_id', inverse_of: :question_options
|
||||
has_many :answers, class_name: 'Legislation::Answer', foreign_key: 'legislation_question_id', dependent: :destroy, inverse_of: :question
|
||||
|
||||
validates :question, presence: true
|
||||
validates :value, presence: true, uniqueness: { scope: :legislation_question_id }
|
||||
|
||||
85
app/models/signature.rb
Normal file
85
app/models/signature.rb
Normal file
@@ -0,0 +1,85 @@
|
||||
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
|
||||
|
||||
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 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
|
||||
@@ -25,6 +25,7 @@ class User < ActiveRecord::Base
|
||||
has_many :notifications
|
||||
has_many :direct_messages_sent, class_name: 'DirectMessage', foreign_key: :sender_id
|
||||
has_many :direct_messages_received, class_name: 'DirectMessage', foreign_key: :receiver_id
|
||||
has_many :legislation_answers, class_name: 'Legislation::Answer', dependent: :destroy, inverse_of: :user
|
||||
belongs_to :geozone
|
||||
|
||||
validates :username, presence: true, if: :username_required?
|
||||
|
||||
@@ -35,8 +35,16 @@
|
||||
</li>
|
||||
<% 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 %>
|
||||
|
||||
<% if feature?(:legislation) %>
|
||||
<li <%= "class=active" if controller_name == "processes" %>>
|
||||
<li <%= "class=active" if controller.class.parent == Admin::Legislation %>>
|
||||
<%= link_to admin_legislation_processes_path do %>
|
||||
<span class="icon-budget"></span><%= t("admin.menu.legislation") %>
|
||||
<% end %>
|
||||
|
||||
@@ -29,7 +29,9 @@
|
||||
<td>
|
||||
<%= content_tag :ul do %>
|
||||
<% question.question_options.each do |question_option| %>
|
||||
<%= content_tag :li, question_option.value %>
|
||||
<%= content_tag :li do %>
|
||||
<%= question_option.value %> (<%= question_option.answers_count %>)
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
</td>
|
||||
|
||||
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 %>
|
||||
<div class="row">
|
||||
<ul id="<%= dom_id(comment) %>" class="comment no-bullet small-12 column">
|
||||
|
||||
<ul id="<%= dom_id(comment) %>" class="comment no-bullet small-12">
|
||||
<li class="comment-body">
|
||||
<% if comment.hidden? || comment.user.hidden? %>
|
||||
<% if comment.children.size > 0 %>
|
||||
<div class="is-deleted">
|
||||
<div class="callout secondary">
|
||||
<p><%= t("comments.comment.deleted") %></p>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -23,82 +22,84 @@
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
<li class="comment-body">
|
||||
<div class="comment-info">
|
||||
<div class="comment-info">
|
||||
|
||||
<% if comment.as_administrator? %>
|
||||
<span class="user-name"><%= t("comments.comment.admin") %> #<%= comment.administrator_id%></span>
|
||||
<% elsif comment.as_moderator? %>
|
||||
<span class="user-name"><%= t("comments.comment.moderator") %> #<%= comment.moderator_id%></span>
|
||||
<% if comment.as_administrator? %>
|
||||
<span class="user-name"><%= t("comments.comment.admin") %> #<%= comment.administrator_id%></span>
|
||||
<% elsif comment.as_moderator? %>
|
||||
<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 %>
|
||||
|
||||
<% if comment.user.hidden? || comment.user.erased? %>
|
||||
<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="user-name"><%= link_to comment.user.name, user_path(comment.user) %></span>
|
||||
<% if comment.user.display_official_position_badge? %>
|
||||
•
|
||||
<span class="label round is-association">
|
||||
<%= t("shared.collective") %>
|
||||
<span class="label round level-<%= comment.user.official_level %>">
|
||||
<%= comment.user.official_position %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if comment.user_id == comment.commentable.author_id %>
|
||||
•
|
||||
<span class="label round is-author">
|
||||
<%= t("comments.comment.author") %>
|
||||
</span>
|
||||
<% end %>
|
||||
|
||||
<% end %>
|
||||
<% if comment.user.verified_organization? %>
|
||||
•
|
||||
<span class="label round is-association">
|
||||
<%= t("shared.collective") %>
|
||||
</span>
|
||||
<% end %>
|
||||
<% if comment.user_id == comment.commentable.author_id %>
|
||||
•
|
||||
<span class="label round is-author">
|
||||
<%= t("comments.comment.author") %>
|
||||
</span>
|
||||
<% 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 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">
|
||||
<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) %>
|
||||
<% if comment.children.size > 0 %>
|
||||
<%= link_to "#{dom_id(comment)}", 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 %>
|
||||
|
||||
<% if user_signed_in? %>
|
||||
<span class="divider"> | </span>
|
||||
<%= link_to(comment_link_text(comment), "",
|
||||
class: "js-add-comment-link", data: {'id': dom_id(comment)}) %>
|
||||
<% if user_signed_in? %>
|
||||
<span class="divider"> | </span>
|
||||
<%= link_to(comment_link_text(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} %>
|
||||
<% end %>
|
||||
</div>
|
||||
</li>
|
||||
<%= render 'comments/form', {commentable: comment.commentable, parent_id: comment.id, toggeable: true} %>
|
||||
<% end %>
|
||||
</div>
|
||||
<% end %>
|
||||
</li>
|
||||
<li>
|
||||
<ul id="<%= dom_id(comment) %>_children" class="no-bullet comment-children">
|
||||
<% child_comments_of(comment).each do |child| %>
|
||||
<%= render 'comments/comment', comment: child %>
|
||||
<li>
|
||||
<%= render 'comments/comment', comment: child %>
|
||||
</li>
|
||||
<% end %>
|
||||
</ul>
|
||||
</ul>
|
||||
</div>
|
||||
</li>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<% cache [locale_and_user_status, parent_id, commentable_cache_key(commentable)] do %>
|
||||
<% 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| %>
|
||||
<%= 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 %>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
<%= form_for(@debate) do |f| %>
|
||||
|
||||
|
||||
<%= render 'shared/errors', resource: @debate %>
|
||||
|
||||
<div class="row">
|
||||
|
||||
@@ -58,6 +58,7 @@
|
||||
</a>
|
||||
<% end %>
|
||||
</div>
|
||||
</aside>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
|
||||
1
app/views/legislation/answers/create.js.erb
Normal file
1
app/views/legislation/answers/create.js.erb
Normal file
@@ -0,0 +1 @@
|
||||
$("#legislation-answer-form").html('<%= j render("legislation/questions/answer_form", process: @process, question: @question, answer: @answer) %>');
|
||||
28
app/views/legislation/questions/_answer_form.html.erb
Normal file
28
app/views/legislation/questions/_answer_form.html.erb
Normal file
@@ -0,0 +1,28 @@
|
||||
<% if question.question_options.any? %>
|
||||
<% if process.open_phase?(:debate) && !answer.persisted? %>
|
||||
|
||||
<%= form_for answer, url: legislation_process_question_answers_path(process, question, answer), remote: true , html: { class: "controls-stacked"} do |f| %>
|
||||
<% question.question_options.each do |question_option| %>
|
||||
<label class="control radio <%= 'active' if @answer.legislation_question_option_id == question_option.id %>">
|
||||
<%= f.radio_button :legislation_question_option_id, question_option.id, label: false %>
|
||||
<span class="control-indicator"></span>
|
||||
<%= question_option.value %>
|
||||
</label>
|
||||
<% end %>
|
||||
<%= f.submit t('legislation.questions.show.answer_question'), class: "button" %>
|
||||
<% end %>
|
||||
|
||||
<% else %>
|
||||
|
||||
<form class="controls-stacked disabled">
|
||||
<% question.question_options.each do |question_option| %>
|
||||
<label class="control radio <%= 'active' if answer.persisted? && (answer.legislation_question_option_id == question_option.id) %>">
|
||||
<input id="quiz-1" name="radio" type="radio" disabled="true">
|
||||
<span class="control-indicator"></span>
|
||||
<%= question_option.value %>
|
||||
</label>
|
||||
<% end %>
|
||||
</form>
|
||||
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -0,0 +1,20 @@
|
||||
<% if user_signed_in? && current_user.organization? %>
|
||||
<div class="participation-not-allowed" style='display:none' aria-hidden="false">
|
||||
<p>
|
||||
<%= t("legislation.questions.participation.organizations") %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif user_signed_in? && current_user.unverified? %>
|
||||
<div class="participation-not-allowed" style='display:none' aria-hidden="false">
|
||||
<p>
|
||||
<%= t("legislation.questions.participation.verified_only",
|
||||
verify_account: link_to(t("legislation.questions.participation.verify_account"), verification_path )).html_safe %>
|
||||
</p>
|
||||
</div>
|
||||
<% elsif !user_signed_in? %>
|
||||
<div class="participation-not-allowed" style='display:none' aria-hidden="false">
|
||||
<%= t("legislation.questions.participation.unauthenticated",
|
||||
signin: link_to(t("legislation.questions.participation.signin"), new_user_session_path),
|
||||
signup: link_to(t("legislation.questions.participation.signup"), new_user_registration_path)).html_safe %>
|
||||
</div>
|
||||
<% end %>
|
||||
@@ -22,17 +22,10 @@
|
||||
<div class="row">
|
||||
<div class="small-12 medium-9 column">
|
||||
<h3 class="quiz-question"><%= @question.title %></h3>
|
||||
<div class="debate-questions">
|
||||
<form class="controls-stacked">
|
||||
<% @question.question_options.each do |question_option| %>
|
||||
<label class="control radio">
|
||||
<input id="quiz-1" name="radio" type="radio">
|
||||
<span class="control-indicator"></span>
|
||||
<%= question_option.value %>
|
||||
</label>
|
||||
<% end %>
|
||||
</form>
|
||||
</div>
|
||||
<div class="debate-questions" id="legislation-answer-form">
|
||||
<%= render 'answer_form', process: @process, question: @question, answer: @answer %>
|
||||
<%= render 'participation_not_allowed' %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<aside class="small-12 medium-3 column">
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<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 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 class="small-12 column">
|
||||
@@ -36,6 +36,7 @@
|
||||
</label>
|
||||
<%= text_field_tag 'advanced_search[date_min]',
|
||||
params[:advanced_search].try(:[], :date_min),
|
||||
type: "date",
|
||||
placeholder: t("shared.advanced_search.date_placeholder"),
|
||||
class: 'js-calendar' %>
|
||||
</div>
|
||||
@@ -45,6 +46,7 @@
|
||||
</label>
|
||||
<%= text_field_tag 'advanced_search[date_max]',
|
||||
params[:advanced_search].try(:[], :date_max),
|
||||
type: "date",
|
||||
placeholder: t("shared.advanced_search.date_placeholder"),
|
||||
class: 'js-calendar' %>
|
||||
</div>
|
||||
|
||||
@@ -95,6 +95,8 @@ search:
|
||||
# - '{devise,simple_form}.*'
|
||||
ignore_missing:
|
||||
- 'unauthorized.*'
|
||||
- 'activerecord.models.proposal'
|
||||
- 'activerecord.models.spending_proposal'
|
||||
- 'activerecord.errors.models.proposal_notification.*'
|
||||
- 'activerecord.errors.models.direct_message.*'
|
||||
- 'errors.messages.blank'
|
||||
|
||||
@@ -6,7 +6,7 @@ end
|
||||
Delayed::Worker.destroy_failed_jobs = false
|
||||
Delayed::Worker.sleep_delay = 2
|
||||
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.default_queue_name = 'default'
|
||||
Delayed::Worker.raise_signal_exceptions = :term
|
||||
|
||||
@@ -12,7 +12,11 @@ Devise.setup do |config|
|
||||
# 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
|
||||
# with default "from" parameter.
|
||||
config.mailer_sender = 'noreply@consul.es'
|
||||
if Rails.env.test?
|
||||
config.mailer_sender = "noreply@example.org"
|
||||
else
|
||||
config.mailer_sender = "#{Setting['mailer_from_name']} <#{Setting['mailer_from_address']}>"
|
||||
end
|
||||
|
||||
# Configure the class responsible to send e-mails.
|
||||
config.mailer = 'DeviseMailer'
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
ActsAsVotable::Vote.class_eval do
|
||||
belongs_to :signature
|
||||
|
||||
def self.for_debates(debates)
|
||||
where(votable_type: 'Debate', votable_id: debates)
|
||||
end
|
||||
@@ -14,4 +16,5 @@ ActsAsVotable::Vote.class_eval do
|
||||
def value
|
||||
vote_flag
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -40,6 +40,15 @@ en:
|
||||
legislation/draft_versions:
|
||||
one: "Draft version"
|
||||
other: "Draft versions"
|
||||
legislation/questions:
|
||||
one: "Question"
|
||||
other: "Questions"
|
||||
legislation/question_options:
|
||||
one: "Question option"
|
||||
other: "Question options"
|
||||
legislation/answers:
|
||||
one: "Answer"
|
||||
other: "Answers"
|
||||
attributes:
|
||||
comment:
|
||||
body: "Comment"
|
||||
@@ -75,6 +84,10 @@ en:
|
||||
external_url: "Link to additional documentation"
|
||||
geozone_id: "Scope of operation"
|
||||
title: "Title"
|
||||
signature_sheet:
|
||||
signable_type: "Signable type"
|
||||
signable_id: "Signable ID"
|
||||
document_numbers: "Documents numbers"
|
||||
legislation/process:
|
||||
title: Process Title
|
||||
description: Description
|
||||
@@ -95,6 +108,10 @@ en:
|
||||
changelog: Changes
|
||||
status: Status
|
||||
final_version: Final version
|
||||
legislation/questions:
|
||||
title: "Title"
|
||||
legislation/question_options:
|
||||
value: "Value"
|
||||
errors:
|
||||
models:
|
||||
user:
|
||||
@@ -117,3 +134,8 @@ en:
|
||||
attributes:
|
||||
minimum_interval:
|
||||
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'
|
||||
|
||||
@@ -40,6 +40,15 @@ es:
|
||||
legislation/draft_texts:
|
||||
one: "Borrador"
|
||||
other: "Borradores"
|
||||
legislation/questions:
|
||||
one: "Pregunta"
|
||||
other: "Preguntas"
|
||||
legislation/question_options:
|
||||
one: "Opción de respuesta cerrada"
|
||||
other: "Opciones de respuesta cerrada"
|
||||
legislation/answers:
|
||||
one: "Respuesta"
|
||||
other: "Respuestas"
|
||||
attributes:
|
||||
comment:
|
||||
body: "Comentario"
|
||||
@@ -75,6 +84,10 @@ es:
|
||||
external_url: "Enlace a documentación adicional"
|
||||
geozone_id: "Ámbito de actuación"
|
||||
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"
|
||||
legislation/process:
|
||||
title: Título del proceso
|
||||
description: En qué consiste
|
||||
@@ -95,6 +108,10 @@ es:
|
||||
changelog: Cambios
|
||||
status: Estado
|
||||
final_version: Versión final
|
||||
legislation/questions:
|
||||
title: "Título"
|
||||
legislation/question_options:
|
||||
value: "Valor"
|
||||
errors:
|
||||
models:
|
||||
user:
|
||||
@@ -117,3 +134,8 @@ es:
|
||||
attributes:
|
||||
minimum_interval:
|
||||
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'
|
||||
|
||||
@@ -187,6 +187,7 @@ en:
|
||||
settings: Configuration settings
|
||||
spending_proposals: Spending proposals
|
||||
stats: Statistics
|
||||
signature_sheets: Signature Sheets
|
||||
legislation: Collaborative Legislation
|
||||
moderators:
|
||||
index:
|
||||
@@ -372,6 +373,31 @@ en:
|
||||
delete:
|
||||
success: Geozone successfully deleted
|
||||
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:
|
||||
show:
|
||||
stats_title: Stats
|
||||
|
||||
@@ -185,6 +185,7 @@ es:
|
||||
settings: Configuración global
|
||||
spending_proposals: Propuestas de inversión
|
||||
stats: Estadísticas
|
||||
signature_sheets: Hojas de firmas
|
||||
legislation: Legislación colaborativa
|
||||
moderators:
|
||||
index:
|
||||
@@ -370,6 +371,31 @@ es:
|
||||
delete:
|
||||
success: Distrito borrado correctamente
|
||||
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:
|
||||
show:
|
||||
stats_title: Estadísticas
|
||||
|
||||
@@ -154,6 +154,7 @@ en:
|
||||
spending_proposal: Spending proposal
|
||||
user: Account
|
||||
verification/sms: phone
|
||||
signature_sheet: Signature sheet
|
||||
geozones:
|
||||
none: All city
|
||||
all: All scopes
|
||||
@@ -269,6 +270,7 @@ en:
|
||||
other: "%{count} comments"
|
||||
debate: Debate
|
||||
show:
|
||||
answer_question: Submit answer
|
||||
comments: Comments
|
||||
next_question: Next question
|
||||
share: Share
|
||||
@@ -276,6 +278,14 @@ en:
|
||||
share_facebook: Share on Facebook
|
||||
share_gplus: Share on Google+
|
||||
title: Collaborative legislation process
|
||||
participation:
|
||||
phase_not_open: This phase is not open
|
||||
organizations: Organisations are not permitted to participate in the debate
|
||||
signin: Sign in
|
||||
signup: Sign up
|
||||
unauthenticated: You must %{signin} or %{signup} to participate.
|
||||
verified_only: Only verified users can participate, %{verify_account}.
|
||||
verify_account: verify your account
|
||||
locale: English
|
||||
notifications:
|
||||
index:
|
||||
|
||||
@@ -154,6 +154,7 @@ es:
|
||||
spending_proposal: la propuesta de gasto
|
||||
user: la cuenta
|
||||
verification/sms: el teléfono
|
||||
signature_sheet: la hoja de firmas
|
||||
geozones:
|
||||
none: Toda la ciudad
|
||||
all: Todos los ámbitos
|
||||
@@ -269,6 +270,7 @@ es:
|
||||
other: "%{count} comentarios"
|
||||
debate: Debate
|
||||
show:
|
||||
answer_question: Enviar respuesta
|
||||
comments: Comentarios
|
||||
next_question: Siguiente pregunta
|
||||
share: Compartir
|
||||
@@ -276,6 +278,14 @@ es:
|
||||
share_facebook: Compartir en Facebook
|
||||
share_gplus: Compartir en Google+
|
||||
title: Proceso de legislación colaborativa
|
||||
participation:
|
||||
phase_not_open: Esta fase no está abierta
|
||||
organizations: Las organizaciones no pueden participar en el debate
|
||||
signin: iniciar sesión
|
||||
signup: registrarte
|
||||
unauthenticated: Necesitas %{signin} o %{signup} para participar en el debate.
|
||||
verified_only: Solo los usuarios verificados pueden participar en el debate, %{verify_account}.
|
||||
verify_account: verifica tu cuenta
|
||||
locale: Español
|
||||
notifications:
|
||||
index:
|
||||
|
||||
@@ -9,7 +9,7 @@ en:
|
||||
proposal: "Proposal created successfully."
|
||||
proposal_notification: "Your message has been sent correctly."
|
||||
spending_proposal: "Spending proposal created successfully. You can access it from %{activity}"
|
||||
|
||||
signature_sheet: "Signature sheet created successfully"
|
||||
save_changes:
|
||||
notice: Changes saved
|
||||
update:
|
||||
|
||||
@@ -9,6 +9,7 @@ es:
|
||||
proposal: "Propuesta creada correctamente."
|
||||
proposal_notification: "Tu message ha sido enviado correctamente."
|
||||
spending_proposal: "Propuesta de inversión creada correctamente. Puedes acceder a ella desde %{activity}"
|
||||
signature_sheet: "Hoja de firmas creada correctamente"
|
||||
save_changes:
|
||||
notice: Cambios guardados
|
||||
update:
|
||||
|
||||
@@ -27,7 +27,10 @@ en:
|
||||
facebook_login: Facebook login
|
||||
google_login: Google login
|
||||
debates: Debates
|
||||
signature_sheets: Signature sheets
|
||||
spending_proposals: Investment projects
|
||||
spending_proposal_features:
|
||||
voting_allowed: Voting on investment projects
|
||||
legislation: Legislation
|
||||
mailer_from_name: Origin email name
|
||||
mailer_from_address: Origin email address
|
||||
|
||||
@@ -27,7 +27,10 @@ es:
|
||||
facebook_login: Registro con Facebook
|
||||
google_login: Registro con Google
|
||||
debates: Debates
|
||||
signature_sheets: Hojas de firmas
|
||||
spending_proposals: Propuestas de inversión
|
||||
spending_proposal_features:
|
||||
voting_allowed: Votaciones sobre propuestas de inversión.
|
||||
legislation: Legislación
|
||||
mailer_from_name: Nombre email remitente
|
||||
mailer_from_address: Dirección email remitente
|
||||
|
||||
@@ -169,6 +169,8 @@ Rails.application.routes.draw do
|
||||
get :summary, on: :collection
|
||||
end
|
||||
|
||||
resources :signature_sheets, only: [:index, :new, :create, :show]
|
||||
|
||||
resources :banners, only: [:index, :new, :create, :edit, :update, :destroy] do
|
||||
collection { get :search}
|
||||
end
|
||||
|
||||
@@ -30,9 +30,13 @@ Setting.create(key: 'feature.spending_proposal_features.voting_allowed', value:
|
||||
Setting.create(key: 'feature.twitter_login', value: "true")
|
||||
Setting.create(key: 'feature.facebook_login', value: "true")
|
||||
Setting.create(key: 'feature.google_login', value: "true")
|
||||
Setting.create(key: 'feature.signature_sheets', value: "true")
|
||||
Setting.create(key: 'feature.legislation', value: "true")
|
||||
Setting.create(key: 'per_page_code', value: "")
|
||||
Setting.create(key: 'comments_body_max_length', value: '1000')
|
||||
Setting.create(key: 'mailer_from_name', value: 'Consul')
|
||||
Setting.create(key: 'mailer_from_address', value: 'noreply@consul.dev')
|
||||
|
||||
|
||||
puts "Creating Geozones"
|
||||
('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
|
||||
13
db/migrate/20161222115744_create_legislation_answers.rb
Normal file
13
db/migrate/20161222115744_create_legislation_answers.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
class CreateLegislationAnswers < ActiveRecord::Migration
|
||||
def change
|
||||
create_table :legislation_answers do |t|
|
||||
t.references :legislation_question, index: true
|
||||
t.references :legislation_question_option, index: true
|
||||
t.references :user, index: true
|
||||
|
||||
t.datetime :hidden_at, index: true
|
||||
|
||||
t.timestamps null: false
|
||||
end
|
||||
end
|
||||
end
|
||||
42
db/schema.rb
42
db/schema.rb
@@ -123,10 +123,10 @@ ActiveRecord::Schema.define(version: 20161222180927) do
|
||||
t.string "visit_id"
|
||||
t.datetime "hidden_at"
|
||||
t.integer "flags_count", default: 0
|
||||
t.datetime "ignored_flag_at"
|
||||
t.integer "cached_votes_total", default: 0
|
||||
t.integer "cached_votes_up", default: 0
|
||||
t.integer "cached_votes_down", default: 0
|
||||
t.datetime "ignored_flag_at"
|
||||
t.integer "comments_count", default: 0
|
||||
t.datetime "confirmed_hide_at"
|
||||
t.integer "cached_anonymous_votes_total", default: 0
|
||||
@@ -145,7 +145,6 @@ ActiveRecord::Schema.define(version: 20161222180927) do
|
||||
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", ["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", ["hidden_at"], name: "index_debates_on_hidden_at", using: :btree
|
||||
add_index "debates", ["hot_score"], name: "index_debates_on_hot_score", using: :btree
|
||||
@@ -228,6 +227,20 @@ ActiveRecord::Schema.define(version: 20161222180927) do
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
create_table "legislation_answers", force: :cascade do |t|
|
||||
t.integer "legislation_question_id"
|
||||
t.integer "legislation_question_option_id"
|
||||
t.integer "user_id"
|
||||
t.datetime "hidden_at"
|
||||
t.datetime "created_at", null: false
|
||||
t.datetime "updated_at", null: false
|
||||
end
|
||||
|
||||
add_index "legislation_answers", ["hidden_at"], name: "index_legislation_answers_on_hidden_at", using: :btree
|
||||
add_index "legislation_answers", ["legislation_question_id"], name: "index_legislation_answers_on_legislation_question_id", using: :btree
|
||||
add_index "legislation_answers", ["legislation_question_option_id"], name: "index_legislation_answers_on_legislation_question_option_id", using: :btree
|
||||
add_index "legislation_answers", ["user_id"], name: "index_legislation_answers_on_user_id", using: :btree
|
||||
|
||||
create_table "legislation_draft_versions", force: :cascade do |t|
|
||||
t.integer "legislation_process_id"
|
||||
t.string "title"
|
||||
@@ -382,7 +395,6 @@ ActiveRecord::Schema.define(version: 20161222180927) do
|
||||
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", ["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", ["hidden_at"], name: "index_proposals_on_hidden_at", using: :btree
|
||||
add_index "proposals", ["hot_score"], name: "index_proposals_on_hot_score", using: :btree
|
||||
@@ -398,6 +410,25 @@ ActiveRecord::Schema.define(version: 20161222180927) do
|
||||
|
||||
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|
|
||||
t.string "title"
|
||||
t.text "description"
|
||||
@@ -536,7 +567,8 @@ ActiveRecord::Schema.define(version: 20161222180927) do
|
||||
t.boolean "email_digest", default: true
|
||||
t.boolean "email_on_direct_message", default: true
|
||||
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
|
||||
|
||||
add_index "users", ["confirmation_token"], name: "index_users_on_confirmation_token", unique: true, using: :btree
|
||||
@@ -616,8 +648,10 @@ ActiveRecord::Schema.define(version: 20161222180927) do
|
||||
t.integer "vote_weight"
|
||||
t.datetime "created_at"
|
||||
t.datetime "updated_at"
|
||||
t.integer "signature_id"
|
||||
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", ["voter_id", "voter_type", "vote_scope"], name: "index_votes_on_voter_id_and_voter_type_and_vote_scope", using: :btree
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ Setting['feature.twitter_login'] = true
|
||||
Setting['feature.facebook_login'] = true
|
||||
Setting['feature.google_login'] = true
|
||||
Setting['feature.public_stats'] = true
|
||||
Setting['feature.signature_sheets'] = true
|
||||
Setting['feature.legislation'] = true
|
||||
|
||||
# Spending proposals feature flags
|
||||
@@ -82,3 +83,7 @@ Setting['banner-img.banner-img-three'] = "Banner image 3"
|
||||
# Proposal notifications
|
||||
Setting['proposal_notification_minimum_interval_in_days'] = 3
|
||||
Setting['direct_message_max_per_day'] = 3
|
||||
|
||||
# Email settings
|
||||
Setting['mailer_from_name'] = 'Consul'
|
||||
Setting['mailer_from_address'] = 'noreply@consul.dev'
|
||||
|
||||
@@ -74,7 +74,7 @@ class CensusApi
|
||||
if end_point_available?
|
||||
client.call(:get_habita_datos, message: request(document_type, document_number)).body
|
||||
else
|
||||
stubbed_response_body
|
||||
stubbed_response(document_type, document_number)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -97,8 +97,20 @@ class CensusApi
|
||||
Rails.env.staging? || Rails.env.preproduction? || Rails.env.production?
|
||||
end
|
||||
|
||||
def stubbed_response_body
|
||||
{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"}}}}}
|
||||
def stubbed_response(document_type, document_number)
|
||||
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
|
||||
|
||||
def is_dni?(document_type)
|
||||
|
||||
43
spec/controllers/legislation/answers_controller_spec.rb
Normal file
43
spec/controllers/legislation/answers_controller_spec.rb
Normal file
@@ -0,0 +1,43 @@
|
||||
require 'rails_helper'
|
||||
|
||||
describe Legislation::AnswersController do
|
||||
|
||||
describe 'POST create' do
|
||||
before(:each) do
|
||||
InvisibleCaptcha.timestamp_enabled = false
|
||||
@process = create(:legislation_process, debate_start_date: Date.current - 3.day, debate_end_date: Date.current + 2.days)
|
||||
@question = create(:legislation_question, process: @process, title: "Question 1")
|
||||
@question_option = create(:legislation_question_option, question: @question, value: "Yes")
|
||||
@user = create(:user, :level_two)
|
||||
end
|
||||
|
||||
after(:each) do
|
||||
InvisibleCaptcha.timestamp_enabled = true
|
||||
end
|
||||
|
||||
it 'should create an ahoy event' do
|
||||
sign_in @user
|
||||
|
||||
post :create, process_id: @process.id, question_id: @question.id, legislation_answer: { legislation_question_option_id: @question_option.id }
|
||||
expect(Ahoy::Event.where(name: :legislation_answer_created).count).to eq 1
|
||||
expect(Ahoy::Event.last.properties['legislation_answer_id']).to eq Legislation::Answer.last.id
|
||||
end
|
||||
|
||||
it 'should create an answer if the process debate phase is open' do
|
||||
sign_in @user
|
||||
|
||||
expect do
|
||||
xhr :post, :create, process_id: @process.id, question_id: @question.id, legislation_answer: { legislation_question_option_id: @question_option.id }
|
||||
end.to change { @question.reload.answers_count }.by(1)
|
||||
end
|
||||
|
||||
it 'should not create an answer if the process debate phase is not open' do
|
||||
sign_in @user
|
||||
@process.update_attribute(:debate_end_date, Date.current - 1.day)
|
||||
|
||||
expect do
|
||||
xhr :post, :create, process_id: @process.id, question_id: @question.id, legislation_answer: { legislation_question_option_id: @question_option.id }
|
||||
end.to_not change { @question.reload.answers_count }
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -344,6 +344,17 @@ FactoryGirl.define do
|
||||
association :receiver, factory: :user
|
||||
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
|
||||
|
||||
factory :legislation_process, class: 'Legislation::Process' do
|
||||
title "A collaborative legislation process"
|
||||
description "Description of the process"
|
||||
@@ -400,4 +411,10 @@ FactoryGirl.define do
|
||||
question factory: :legislation_question
|
||||
sequence(:value) { |n| "Option #{n}" }
|
||||
end
|
||||
|
||||
factory :legislation_answer, class: 'Legislation::Answer' do
|
||||
question factory: :legislation_question
|
||||
question_option factory: :legislation_question_option
|
||||
user
|
||||
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
|
||||
@@ -1,36 +0,0 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Legislation' do
|
||||
|
||||
context 'process debate page' do
|
||||
scenario 'shows question list' do
|
||||
process = create(:legislation_process, debate_start_date: Date.current - 1.day, debate_end_date: Date.current + 2.days)
|
||||
create(:legislation_question, process: process, title: "Question 1")
|
||||
create(:legislation_question, process: process, title: "Question 2")
|
||||
create(:legislation_question, process: process, title: "Question 3")
|
||||
|
||||
visit legislation_process_path(process)
|
||||
|
||||
expect(page).to have_content("Participate in the debate")
|
||||
|
||||
expect(page).to have_content("Question 1")
|
||||
expect(page).to have_content("Question 2")
|
||||
expect(page).to have_content("Question 3")
|
||||
|
||||
click_link "Question 1"
|
||||
|
||||
expect(page).to have_content("Question 1")
|
||||
expect(page).to have_content("Next question")
|
||||
|
||||
click_link "Next question"
|
||||
|
||||
expect(page).to have_content("Question 2")
|
||||
expect(page).to have_content("Next question")
|
||||
|
||||
click_link "Next question"
|
||||
|
||||
expect(page).to have_content("Question 3")
|
||||
expect(page).to_not have_content("Next question")
|
||||
end
|
||||
end
|
||||
end
|
||||
110
spec/features/legislation/questions_spec.rb
Normal file
110
spec/features/legislation/questions_spec.rb
Normal file
@@ -0,0 +1,110 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Legislation' do
|
||||
context 'process debate page' do
|
||||
before(:each) do
|
||||
@process = create(:legislation_process, debate_start_date: Date.current - 3.day, debate_end_date: Date.current + 2.days)
|
||||
create(:legislation_question, process: @process, title: "Question 1")
|
||||
create(:legislation_question, process: @process, title: "Question 2")
|
||||
create(:legislation_question, process: @process, title: "Question 3")
|
||||
end
|
||||
|
||||
scenario 'shows question list' do
|
||||
visit legislation_process_path(@process)
|
||||
|
||||
expect(page).to have_content("Participate in the debate")
|
||||
|
||||
expect(page).to have_content("Question 1")
|
||||
expect(page).to have_content("Question 2")
|
||||
expect(page).to have_content("Question 3")
|
||||
|
||||
click_link "Question 1"
|
||||
|
||||
expect(page).to have_content("Question 1")
|
||||
expect(page).to have_content("Next question")
|
||||
|
||||
click_link "Next question"
|
||||
|
||||
expect(page).to have_content("Question 2")
|
||||
expect(page).to have_content("Next question")
|
||||
|
||||
click_link "Next question"
|
||||
|
||||
expect(page).to have_content("Question 3")
|
||||
expect(page).to_not have_content("Next question")
|
||||
end
|
||||
|
||||
scenario 'shows question page' do
|
||||
visit legislation_process_question_path(@process, @process.questions.first)
|
||||
|
||||
expect(page).to have_content("Question 1")
|
||||
expect(page).to have_content("Comments (0)")
|
||||
end
|
||||
|
||||
scenario 'shows next question link in question page' do
|
||||
visit legislation_process_question_path(@process, @process.questions.first)
|
||||
|
||||
expect(page).to have_content("Question 1")
|
||||
expect(page).to have_content("Next question")
|
||||
|
||||
click_link "Next question"
|
||||
|
||||
expect(page).to have_content("Question 2")
|
||||
expect(page).to have_content("Next question")
|
||||
|
||||
click_link "Next question"
|
||||
|
||||
expect(page).to have_content("Question 3")
|
||||
expect(page).to_not have_content("Next question")
|
||||
end
|
||||
|
||||
scenario 'answer question' do
|
||||
question = @process.questions.first
|
||||
create(:legislation_question_option, question: question, value: "Yes")
|
||||
create(:legislation_question_option, question: question, value: "No")
|
||||
option = create(:legislation_question_option, question: question, value: "I don't know")
|
||||
user = create(:user, :level_two)
|
||||
|
||||
login_as(user)
|
||||
|
||||
visit legislation_process_question_path(@process, question)
|
||||
|
||||
expect(page).to have_selector(:radio_button, "Yes")
|
||||
expect(page).to have_selector(:radio_button, "No")
|
||||
expect(page).to have_selector(:radio_button, "I don't know")
|
||||
expect(page).to have_selector(:link_or_button, "Submit answer")
|
||||
|
||||
choose("I don't know")
|
||||
click_button "Submit answer"
|
||||
|
||||
within(:css, "label.active") do
|
||||
expect(page).to have_content("I don't know")
|
||||
expect(page).to_not have_content("Yes")
|
||||
expect(page).to_not have_content("No")
|
||||
end
|
||||
expect(page).to_not have_selector(:link_or_button, "Submit answer")
|
||||
|
||||
expect(question.reload.answers_count).to eq(1)
|
||||
expect(option.reload.answers_count).to eq(1)
|
||||
end
|
||||
|
||||
scenario 'cannot answer question when phase not open' do
|
||||
@process.update_attribute(:debate_end_date, Date.current - 1.day)
|
||||
question = @process.questions.first
|
||||
create(:legislation_question_option, question: question, value: "Yes")
|
||||
create(:legislation_question_option, question: question, value: "No")
|
||||
create(:legislation_question_option, question: question, value: "I don't know")
|
||||
user = create(:user, :level_two)
|
||||
|
||||
login_as(user)
|
||||
|
||||
visit legislation_process_question_path(@process, question)
|
||||
|
||||
expect(page).to have_selector(:radio_button, "Yes", disabled: true)
|
||||
expect(page).to have_selector(:radio_button, "No", disabled: true)
|
||||
expect(page).to have_selector(:radio_button, "I don't know", disabled: true)
|
||||
|
||||
expect(page).to_not have_selector(:link_or_button, "Submit answer")
|
||||
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
|
||||
|
||||
visit management_document_verifications_path
|
||||
fill_in 'document_verification_document_number', with: '1234'
|
||||
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||
click_button 'Check'
|
||||
|
||||
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)
|
||||
|
||||
visit management_document_verifications_path
|
||||
fill_in 'document_verification_document_number', with: '1234'
|
||||
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||
click_button 'Check'
|
||||
|
||||
expect(page).to have_content "You must be over 16 to verify your account."
|
||||
|
||||
@@ -8,7 +8,7 @@ feature 'EmailVerifications' do
|
||||
user = create(:user)
|
||||
|
||||
visit management_document_verifications_path
|
||||
fill_in 'document_verification_document_number', with: '1234'
|
||||
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||
click_button 'Check'
|
||||
|
||||
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 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
|
||||
end
|
||||
|
||||
|
||||
@@ -57,7 +57,7 @@ feature 'Managed User' do
|
||||
user = create(:user)
|
||||
|
||||
visit management_document_verifications_path
|
||||
fill_in 'document_verification_document_number', with: '1234'
|
||||
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||
click_button 'Check'
|
||||
|
||||
within(".account-info") do
|
||||
@@ -66,7 +66,7 @@ feature 'Managed User' do
|
||||
expect(page).not_to have_content "Email"
|
||||
expect(page).to have_content "Document type"
|
||||
expect(page).to have_content "Document number"
|
||||
expect(page).to have_content "1234"
|
||||
expect(page).to have_content "12345678Z"
|
||||
end
|
||||
|
||||
expect(page).to have_content "Please introduce the email used on the account"
|
||||
@@ -88,7 +88,7 @@ feature 'Managed User' do
|
||||
login_as_manager
|
||||
|
||||
visit management_document_verifications_path
|
||||
fill_in 'document_verification_document_number', with: '1234'
|
||||
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||
click_button 'Check'
|
||||
|
||||
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
|
||||
|
||||
visit management_document_verifications_path
|
||||
fill_in 'document_verification_document_number', with: '1234'
|
||||
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||
click_button 'Check'
|
||||
|
||||
expect(page).to have_content "Please introduce the email used on the account"
|
||||
@@ -45,10 +45,10 @@ feature 'Users' do
|
||||
end
|
||||
|
||||
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
|
||||
fill_in 'document_verification_document_number', with: '13579'
|
||||
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||
click_button 'Check'
|
||||
|
||||
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}"
|
||||
|
||||
visit management_document_verifications_path
|
||||
fill_in 'document_verification_document_number', with: '13579'
|
||||
fill_in 'document_verification_document_number', with: '12345678Z'
|
||||
click_button 'Check'
|
||||
|
||||
expect(page).to have_content "no user account associated to it"
|
||||
|
||||
39
spec/models/legislation/answer_spec.rb
Normal file
39
spec/models/legislation/answer_spec.rb
Normal file
@@ -0,0 +1,39 @@
|
||||
require 'rails_helper'
|
||||
|
||||
RSpec.describe Legislation::Answer, type: :model do
|
||||
let(:legislation_answer) { build(:legislation_answer) }
|
||||
|
||||
it "should be valid" do
|
||||
expect(legislation_answer).to be_valid
|
||||
end
|
||||
|
||||
it "counts answers" do
|
||||
question = create(:legislation_question)
|
||||
option_1 = create(:legislation_question_option, question: question, value: 'Yes')
|
||||
option_2 = create(:legislation_question_option, question: question, value: 'No')
|
||||
|
||||
answer = create(:legislation_answer, question: question, question_option: option_2)
|
||||
|
||||
expect(answer).to be_valid
|
||||
expect(question.answers_count).to eq 1
|
||||
expect(option_2.answers_count).to eq 1
|
||||
expect(option_1.answers_count).to eq 0
|
||||
end
|
||||
|
||||
it "can't answer same question more than once" do
|
||||
question = create(:legislation_question)
|
||||
option_1 = create(:legislation_question_option, question: question, value: 'Yes')
|
||||
option_2 = create(:legislation_question_option, question: question, value: 'No')
|
||||
user = create(:user)
|
||||
|
||||
answer = create(:legislation_answer, question: question, question_option: option_2, user: user)
|
||||
expect(answer).to be_valid
|
||||
|
||||
second_answer = build(:legislation_answer, question: question, question_option: option_1, user: user)
|
||||
expect(second_answer).to be_invalid
|
||||
|
||||
expect(question.answers_count).to eq 1
|
||||
expect(option_2.answers_count).to eq 1
|
||||
expect(option_1.answers_count).to eq 0
|
||||
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
|
||||
171
spec/models/signature_spec.rb
Normal file
171
spec/models/signature_spec.rb
Normal file
@@ -0,0 +1,171 @@
|
||||
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
|
||||
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 "#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