diff --git a/app/assets/javascripts/votes.js.coffee b/app/assets/javascripts/votes.js.coffee index 43469909d..e4223c644 100644 --- a/app/assets/javascripts/votes.js.coffee +++ b/app/assets/javascripts/votes.js.coffee @@ -5,11 +5,13 @@ App.Votes = $("div.anonymous-votes", votes).show(); $("div.organizations-votes", votes).show(); $("div.not-logged", votes).show(); + $("div.no-supports-allowed", votes).show(); $("div.logged", votes).hide(); , -> $("div.anonymous-votes", votes).hide(); $("div.organizations-votes", votes).hide(); $("div.not-logged", votes).hide(); + $("div.no-supports-allowed", votes).hide(); $("div.logged", votes).show(); initialize: -> diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss index 1773ef8da..0873e7c7c 100644 --- a/app/assets/stylesheets/participation.scss +++ b/app/assets/stylesheets/participation.scss @@ -240,7 +240,7 @@ } } - .anonymous-votes, .organizations-votes { + .anonymous-votes, .organizations-votes, .no-supports-allowed { background: $warning-bg; color: $warning-color; height: 100%; @@ -847,16 +847,13 @@ color: $budget; } - .not-logged, - .organizations-votes, - .anonymous-votes { + .no-supports-allowed { background: rgba(69,67,114,.96); color: white; padding: rem-calc(12); } - .anonymous-votes p, .anonymous-votes a, - .organizations-votes p { + .no-supports-allowed p, .no-supports-allowed a { color: white; } } diff --git a/app/models/spending_proposal.rb b/app/models/spending_proposal.rb index 66c6cb2ad..7a3dda7c6 100644 --- a/app/models/spending_proposal.rb +++ b/app/models/spending_proposal.rb @@ -112,8 +112,16 @@ class SpendingProposal < ActiveRecord::Base update(unfeasible_email_sent_at: Time.now) end + def reason_for_not_being_votable_by(user) + return :not_logged_in unless user + return :not_verified unless user.can?(:vote, SpendingProposal) + return :unfeasible if unfeasible? + return :organization if user.organization? + return :not_voting_allowed if Setting["feature.spending_proposal_features.voting_allowed"].blank? + end + def votable_by?(user) - user && user.level_two_or_three_verified? + reason_for_not_being_votable_by(user).blank? end def register_vote(user, vote_value) diff --git a/app/models/user.rb b/app/models/user.rb index bc4b0f120..f7980c796 100644 --- a/app/models/user.rb +++ b/app/models/user.rb @@ -222,6 +222,11 @@ class User < ActiveRecord::Base self.update(registering_with_oauth: true, email: nil) end + def ability + @ability ||= Ability.new(self) + end + delegate :can?, :cannot?, to: :ability + private def clean_document_number self.document_number = self.document_number.gsub(/[^a-z0-9]+/i, "").upcase unless self.document_number.blank? diff --git a/app/views/spending_proposals/_votes.html.erb b/app/views/spending_proposals/_votes.html.erb index ed8e61b2d..8dbc2aa3f 100644 --- a/app/views/spending_proposals/_votes.html.erb +++ b/app/views/spending_proposals/_votes.html.erb @@ -18,25 +18,18 @@ <% end %> - <% if user_signed_in? && current_user.organization? %> - - <% elsif user_signed_in? && !spending_proposal.votable_by?(current_user)%> - - <% elsif !user_signed_in? %> - + <% reason = spending_proposal.reason_for_not_being_votable_by(current_user) %> + + <% if reason.present? && !voted_for?(@spending_proposal_votes, spending_proposal) %> + <% end %> <% if voted_for?(@spending_proposal_votes, spending_proposal) && setting['twitter_handle'] %> diff --git a/config/locales/en.yml b/config/locales/en.yml index 639aa3fb9..8609c079c 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -500,6 +500,12 @@ en: unauthenticated: You must %{signin} or %{signup} to continue. verified_only: Only verified users can vote on proposals; %{verify_account}. verify_account: verify your account + spending_proposals: + not_logged_in: You must %{signin} or %{signup} to continue. + not_verified: Only verified users can vote on proposals; %{verify_account}. + organization: Organisations are not permitted to vote + unfeasible: Unfeasible investment projects can not be supported + not_voting_allowed: Voting phase is closed welcome: debates: alt: Icon debates diff --git a/config/locales/es.yml b/config/locales/es.yml index c39ef965a..a15528d5a 100755 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -500,6 +500,12 @@ es: unauthenticated: Necesitas %{signin} o %{signup} para continuar. verified_only: Las propuestas sólo pueden ser votadas por usuarios verificados, %{verify_account}. verify_account: verifica tu cuenta + spending_proposals: + not_logged_in: Necesitas %{signin} o %{signup} para continuar. + not_verified: Las propuestas de inversión sólo pueden ser apoyadas por usuarios verificados, %{verify_account}. + organization: Las organizaciones no pueden votar. + unfeasible: No se pueden votar propuestas inviables. + not_voting_allowed: El periodo de votación está cerrado. welcome: debates: alt: Icono debates diff --git a/spec/features/votes_spec.rb b/spec/features/votes_spec.rb index 632162c3c..2ae64effe 100644 --- a/spec/features/votes_spec.rb +++ b/spec/features/votes_spec.rb @@ -435,4 +435,24 @@ feature 'Votes' do end end end + + scenario 'Disable voting on spending proposals', :js do + login_as(@manuela) + Setting["feature.spending_proposal_features.voting_allowed"] = nil + spending_proposal = create(:spending_proposal) + + visit spending_proposals_path + + within("#spending_proposal_#{spending_proposal.id}") do + find("div.supports").hover + expect_message_voting_not_allowed + end + + visit spending_proposal_path(spending_proposal) + + within("#spending_proposal_#{spending_proposal.id}") do + find("div.supports").hover + expect_message_voting_not_allowed + end + end end diff --git a/spec/models/spending_proposal_spec.rb b/spec/models/spending_proposal_spec.rb index e3b7629d7..5bff7cadd 100644 --- a/spec/models/spending_proposal_spec.rb +++ b/spec/models/spending_proposal_spec.rb @@ -261,6 +261,49 @@ describe SpendingProposal do end end + describe 'Supports' do + let(:user) { create(:user, :level_two) } + let(:luser) { create(:user) } + let(:district) { create(:geozone) } + let(:city_sp) { create(:spending_proposal) } + let(:district_sp) { create(:spending_proposal, geozone: district) } + + describe '#reason_for_not_being_votable_by' do + it "rejects not logged in users" do + expect(city_sp.reason_for_not_being_votable_by(nil)).to eq(:not_logged_in) + expect(district_sp.reason_for_not_being_votable_by(nil)).to eq(:not_logged_in) + end + + it "rejects not verified users" do + expect(city_sp.reason_for_not_being_votable_by(luser)).to eq(:not_verified) + expect(district_sp.reason_for_not_being_votable_by(luser)).to eq(:not_verified) + end + + it "rejects unfeasible spending proposals" do + unfeasible = create(:spending_proposal, feasible: false, valuation_finished: true) + expect(unfeasible.reason_for_not_being_votable_by(user)).to eq(:unfeasible) + end + + it "rejects organizations" do + create(:organization, user: user) + expect(city_sp.reason_for_not_being_votable_by(user)).to eq(:organization) + expect(district_sp.reason_for_not_being_votable_by(user)).to eq(:organization) + end + + it "rejects votes when voting is not allowed (via admin setting)" do + Setting["feature.spending_proposal_features.voting_allowed"] = nil + expect(city_sp.reason_for_not_being_votable_by(user)).to eq(:not_voting_allowed) + expect(district_sp.reason_for_not_being_votable_by(user)).to eq(:not_voting_allowed) + end + + it "accepts valid votes when voting is allowed" do + Setting["feature.spending_proposal_features.voting_allowed"] = true + expect(city_sp.reason_for_not_being_votable_by(user)).to be_nil + expect(district_sp.reason_for_not_being_votable_by(user)).to be_nil + end + end + end + describe "responsible_name" do let(:user) { create(:user, document_number: "123456") } let!(:spending_proposal) { create(:spending_proposal, author: user) } diff --git a/spec/support/common_actions.rb b/spec/support/common_actions.rb index f3d4a8697..762119130 100644 --- a/spec/support/common_actions.rb +++ b/spec/support/common_actions.rb @@ -174,6 +174,11 @@ module CommonActions expect(page).to have_selector('.in-favor a', visible: false) end + def expect_message_voting_not_allowed + expect(page).to have_content 'Voting phase is closed' + expect(page).to have_selector('.in-favor a', visible: false) + end + def create_featured_proposals [create(:proposal, :with_confidence_score, cached_votes_up: 100), create(:proposal, :with_confidence_score, cached_votes_up: 90),