Merge pull request #913 from consul/investment-proposal-show
Allows users to view their own spending proposals
This commit is contained in:
@@ -1,11 +1,12 @@
|
||||
class SpendingProposalsController < ApplicationController
|
||||
include FeatureFlags
|
||||
|
||||
before_action :authenticate_user!, except: [:index]
|
||||
before_action :verify_valuator, only: [:show]
|
||||
|
||||
load_and_authorize_resource
|
||||
|
||||
before_action :authenticate_user!, except: [:index]
|
||||
before_action :verify_access, only: [:show]
|
||||
before_filter -> { flash.now[:notice] = flash[:notice].html_safe if flash[:html_safe] && flash[:notice] }
|
||||
|
||||
feature_flag :spending_proposals
|
||||
|
||||
def index
|
||||
@@ -20,7 +21,8 @@ class SpendingProposalsController < ApplicationController
|
||||
@spending_proposal.author = current_user
|
||||
|
||||
if @spending_proposal.save_with_captcha
|
||||
redirect_to spending_proposals_path, notice: t("flash.actions.create.spending_proposal")
|
||||
notice = t('flash.actions.create.spending_proposal', activity: "<a href='#{user_path(current_user, filter: :spending_proposals)}'>#{t('layouts.header.my_activity_link')}</a>")
|
||||
redirect_to @spending_proposal, notice: notice, flash: { html_safe: true }
|
||||
else
|
||||
render :new
|
||||
end
|
||||
@@ -32,8 +34,8 @@ class SpendingProposalsController < ApplicationController
|
||||
params.require(:spending_proposal).permit(:title, :description, :external_url, :geozone_id, :association_name, :terms_of_service, :captcha, :captcha_key)
|
||||
end
|
||||
|
||||
def verify_valuator
|
||||
raise CanCan::AccessDenied unless current_user.try(:valuator?) || current_user.try(:administrator?)
|
||||
def verify_access
|
||||
raise CanCan::AccessDenied unless current_user.try(:valuator?) || current_user.try(:administrator?) || @spending_proposal.author == current_user
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
class UsersController < ApplicationController
|
||||
has_filters %w{proposals debates comments}, only: :show
|
||||
has_filters %w{proposals debates comments spending_proposals}, only: :show
|
||||
|
||||
load_and_authorize_resource
|
||||
helper_method :authorized_for_filter?
|
||||
|
||||
def show
|
||||
load_filtered_activity if valid_access?
|
||||
@@ -12,7 +13,8 @@ class UsersController < ApplicationController
|
||||
@activity_counts = HashWithIndifferentAccess.new(
|
||||
proposals: Proposal.where(author_id: @user.id).count,
|
||||
debates: Debate.where(author_id: @user.id).count,
|
||||
comments: Comment.not_as_admin_or_moderator.where(user_id: @user.id).count)
|
||||
comments: Comment.not_as_admin_or_moderator.where(user_id: @user.id).count,
|
||||
spending_proposals: SpendingProposal.where(author_id: @user.id).count)
|
||||
end
|
||||
|
||||
def load_filtered_activity
|
||||
@@ -21,6 +23,7 @@ class UsersController < ApplicationController
|
||||
when "proposals" then load_proposals
|
||||
when "debates" then load_debates
|
||||
when "comments" then load_comments
|
||||
when "spending_proposals" then load_spending_proposals
|
||||
else load_available_activity
|
||||
end
|
||||
end
|
||||
@@ -35,6 +38,9 @@ class UsersController < ApplicationController
|
||||
elsif @activity_counts[:comments] > 0
|
||||
load_comments
|
||||
@current_filter = "comments"
|
||||
elsif @activity_counts[:spending_proposals] > 0 && author_or_admin?
|
||||
load_spending_proposals
|
||||
@current_filter = "spending_proposals"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -50,11 +56,23 @@ class UsersController < ApplicationController
|
||||
@comments = Comment.not_as_admin_or_moderator.where(user_id: @user.id).includes(:commentable).order(created_at: :desc).page(params[:page])
|
||||
end
|
||||
|
||||
def load_spending_proposals
|
||||
@spending_proposals = SpendingProposal.where(author_id: @user.id).order(created_at: :desc).page(params[:page])
|
||||
end
|
||||
|
||||
def valid_access?
|
||||
@user.public_activity || authorized_current_user?
|
||||
end
|
||||
|
||||
def author_or_admin?
|
||||
@author_or_admin ||= current_user && (current_user == @user || current_user.administrator?)
|
||||
end
|
||||
|
||||
def authorized_current_user?
|
||||
@authorized_current_user ||= current_user && (current_user == @user || current_user.moderator? || current_user.administrator?)
|
||||
end
|
||||
|
||||
def authorized_for_filter?(filter)
|
||||
filter == "spending_proposals" ? author_or_admin? : true
|
||||
end
|
||||
end
|
||||
|
||||
@@ -64,4 +64,8 @@ class SpendingProposal < ActiveRecord::Base
|
||||
end
|
||||
end
|
||||
|
||||
def description
|
||||
super.try :html_safe
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
@@ -1,24 +1,44 @@
|
||||
<span class="flag-content">
|
||||
<% if show_flag_action? comment %>
|
||||
<span class="divider"> | </span>
|
||||
<a class="button" id="flag-expand-comment-<%= comment.id %>" data-dropdown="flag-drop-comment-<%= comment.id %>" aria-controls="flag-drop-comment-<%= comment.id %>" aria-expanded="false" title="<%= t('shared.flag') %>">
|
||||
<i class="icon-flag flag-disable"></i>
|
||||
<a class="button" id="flag-expand-comment-<%= comment.id %>"
|
||||
data-dropdown="flag-drop-comment-<%= comment.id %>"
|
||||
aria-controls="flag-drop-comment-<%= comment.id %>"
|
||||
aria-expanded="false"
|
||||
title="<%= t('shared.flag') %>">
|
||||
|
||||
<i class="icon-flag flag-disable"></i>
|
||||
</a>
|
||||
<ul id="flag-drop-comment-<%= comment.id %>" class="f-dropdown" data-dropdown-content aria-hidden="true" tabindex="-1">
|
||||
<ul id="flag-drop-comment-<%= comment.id %>"
|
||||
class="f-dropdown"
|
||||
data-dropdown-content
|
||||
aria-hidden="true"
|
||||
tabindex="-1">
|
||||
<li>
|
||||
<%= link_to t("shared.flag"), flag_comment_path(comment), method: :put, remote: true, id: "flag-comment-#{comment.id}" %>
|
||||
<%= link_to t("shared.flag"), flag_comment_path(comment), method: :put,
|
||||
remote: true, id: "flag-comment-#{comment.id}" %>
|
||||
</li>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
<% if show_unflag_action? comment %>
|
||||
<span class="divider"> | </span>
|
||||
<a class="button" id="unflag-expand-comment-<%= comment.id %>" data-dropdown="unflag-drop-comment-<%= comment.id %>" aria-controls="unflag-drop-comment-<%= comment.id %>" aria-expanded="false" title="<%= t('shared.unflag') %>">
|
||||
<i class="icon-flag flag-active"></i>
|
||||
<a class="button" id="unflag-expand-comment-<%= comment.id %>"
|
||||
data-dropdown="unflag-drop-comment-<%= comment.id %>"
|
||||
aria-controls="unflag-drop-comment-<%= comment.id %>"
|
||||
aria-expanded="false"
|
||||
title="<%= t('shared.unflag') %>">
|
||||
|
||||
<i class="icon-flag flag-active"></i>
|
||||
</a>
|
||||
<ul id="unflag-drop-comment-<%= comment.id %>" class="f-dropdown" data-dropdown-content aria-hidden="true" tabindex="-1">
|
||||
<ul id="unflag-drop-comment-<%= comment.id %>"
|
||||
class="f-dropdown"
|
||||
data-dropdown-content
|
||||
aria-hidden="true"
|
||||
tabindex="-1">
|
||||
<li>
|
||||
<%= link_to t("shared.unflag"), unflag_comment_path(comment), method: :put, remote: true, id: "unflag-comment-#{comment.id}" %>
|
||||
<%= link_to t("shared.unflag"), unflag_comment_path(comment), method: :put,
|
||||
remote: true, id: "unflag-comment-#{comment.id}" %>
|
||||
</li>
|
||||
</ul>
|
||||
<% end %>
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
<![endif]-->
|
||||
|
||||
<% if notice %>
|
||||
<div class="alert-messages">
|
||||
<div id="notice" class="alert-messages">
|
||||
<div class="row">
|
||||
<div data-alert class="alert-box success radius">
|
||||
<a href="#" class="close" title="<%= t("application.close") %>">×</a>
|
||||
@@ -52,7 +52,7 @@
|
||||
<% end %>
|
||||
|
||||
<% if alert %>
|
||||
<div class="alert-messages">
|
||||
<div id="alert" class="alert-messages">
|
||||
<div class="row">
|
||||
<div data-alert class="alert-box alert radius">
|
||||
<a href="#" class="close" title="<%= t("application.close") %>">×</a>
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
<%= render "proposals" if @proposals.present? %>
|
||||
<%= render "debates" if @debates.present? && feature?(:debates) %>
|
||||
<%= render "comments" if @comments.present? %>
|
||||
<%= render "spending_proposals" if @spending_proposals.present? %>
|
||||
|
||||
13
app/views/users/_spending_proposals.html.erb
Normal file
13
app/views/users/_spending_proposals.html.erb
Normal file
@@ -0,0 +1,13 @@
|
||||
<table class="clear activity-proposals">
|
||||
<% @spending_proposals.each do |spending_proposal| %>
|
||||
<tr id="spending_proposal_<%= spending_proposal.id %>">
|
||||
<td>
|
||||
<%= link_to spending_proposal.title, spending_proposal %>
|
||||
<br>
|
||||
<%= spending_proposal.description %>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</table>
|
||||
|
||||
<%= paginate @spending_proposals %>
|
||||
@@ -14,11 +14,17 @@
|
||||
<dl class="sub-nav margin-top">
|
||||
<% @valid_filters.each do |filter| %>
|
||||
<% if @activity_counts[filter] > 0 %>
|
||||
<% if @current_filter == filter %>
|
||||
<dd class="active"> <%= t("users.show.filters.#{filter}", count: @activity_counts[filter]) %></dd>
|
||||
<% else %>
|
||||
<dd><%= link_to t("users.show.filters.#{filter}", count: @activity_counts[filter]),
|
||||
current_path_with_query_params(filter: filter, page: 1) %></dd>
|
||||
<% if authorized_for_filter?(filter) %>
|
||||
<% if @current_filter == filter %>
|
||||
<dd class="active">
|
||||
<%= t("users.show.filters.#{filter}", count: @activity_counts[filter]) %>
|
||||
</dd>
|
||||
<% else %>
|
||||
<dd>
|
||||
<%= link_to t("users.show.filters.#{filter}", count: @activity_counts[filter]),
|
||||
current_path_with_query_params(filter: filter, page: 1) %>
|
||||
</dd>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
|
||||
@@ -453,6 +453,9 @@ en:
|
||||
proposals:
|
||||
one: 1 Proposal
|
||||
other: "%{count} Proposals"
|
||||
spending_proposals:
|
||||
one: 1 Spending proposal
|
||||
other: "%{count} Spending proposals"
|
||||
no_activity: User has no public activity
|
||||
private_activity: This user decided to keep the activity list private
|
||||
votes:
|
||||
|
||||
@@ -454,6 +454,9 @@ es:
|
||||
proposals:
|
||||
one: 1 Propuesta
|
||||
other: "%{count} Propuestas"
|
||||
spending_proposals:
|
||||
one: 1 Propuesta de inversión
|
||||
other: "%{count} Propuestas de inversión"
|
||||
no_activity: Usuario sin actividad pública
|
||||
private_activity: Este usuario ha decidido mantener en privado su lista de actividades
|
||||
votes:
|
||||
|
||||
@@ -6,7 +6,7 @@ en:
|
||||
notice: "%{resource_name} created successfully."
|
||||
debate: "Debate created successfully."
|
||||
proposal: "Proposal created successfully."
|
||||
spending_proposal: "Spending proposal created successfully."
|
||||
spending_proposal: "Spending proposal created successfully. You can access it from %{activity}"
|
||||
save_changes:
|
||||
notice: Changes saved
|
||||
update:
|
||||
|
||||
@@ -6,7 +6,7 @@ es:
|
||||
notice: "%{resource_name} creado correctamente."
|
||||
debate: "Debate creado correctamente."
|
||||
proposal: "Propuesta creada correctamente."
|
||||
spending_proposal: "Propuesta de gasto creada correctamente."
|
||||
spending_proposal: "Propuesta de inversión creada correctamente. Puedes acceder a ella desde %{activity}"
|
||||
save_changes:
|
||||
notice: Cambios guardados
|
||||
update:
|
||||
|
||||
@@ -2,7 +2,7 @@ require 'rails_helper'
|
||||
|
||||
feature 'Spending proposals' do
|
||||
|
||||
let(:author) { create(:user, :level_two) }
|
||||
let(:author) { create(:user, :level_two, username: 'Isabel') }
|
||||
|
||||
scenario 'Index' do
|
||||
visit spending_proposals_path
|
||||
@@ -33,6 +33,37 @@ feature 'Spending proposals' do
|
||||
click_button 'Create'
|
||||
|
||||
expect(page).to have_content 'Spending proposal created successfully'
|
||||
expect(page).to have_content('Build a skyscraper')
|
||||
expect(page).to have_content('I want to live in a high tower over the clouds')
|
||||
expect(page).to have_content('Isabel')
|
||||
expect(page).to have_content('People of the neighbourhood')
|
||||
expect(page).to have_content('All city')
|
||||
end
|
||||
|
||||
scenario 'Create notice' do
|
||||
login_as(author)
|
||||
|
||||
visit new_spending_proposal_path
|
||||
fill_in 'spending_proposal_title', with: 'Build a skyscraper'
|
||||
fill_in 'spending_proposal_description', with: 'I want to live in a high tower over the clouds'
|
||||
fill_in 'spending_proposal_external_url', with: 'http://http://skyscraperpage.com/'
|
||||
fill_in 'spending_proposal_association_name', with: 'People of the neighbourhood'
|
||||
fill_in 'spending_proposal_captcha', with: correct_captcha_text
|
||||
select 'All city', from: 'spending_proposal_geozone_id'
|
||||
check 'spending_proposal_terms_of_service'
|
||||
|
||||
click_button 'Create'
|
||||
|
||||
expect(page).to have_content 'Spending proposal created successfully'
|
||||
expect(page).to have_content 'You can access it from My activity'
|
||||
|
||||
within "#notice" do
|
||||
click_link 'My activity'
|
||||
end
|
||||
|
||||
expect(current_url).to eq(user_url(author, filter: :spending_proposals))
|
||||
expect(page).to have_content "1 Spending proposal"
|
||||
expect(page).to have_content "Build a skyscraper"
|
||||
end
|
||||
|
||||
scenario 'Captcha is required for proposal creation' do
|
||||
@@ -100,6 +131,24 @@ feature 'Spending proposals' do
|
||||
expect(page).to have_content(spending_proposal.geozone.name)
|
||||
end
|
||||
|
||||
scenario "Show (as author)" do
|
||||
author = create(:user)
|
||||
login_as(author)
|
||||
|
||||
spending_proposal = create(:spending_proposal,
|
||||
geozone: create(:geozone),
|
||||
association_name: 'People of the neighbourhood',
|
||||
author: author)
|
||||
|
||||
visit spending_proposal_path(spending_proposal)
|
||||
|
||||
expect(page).to have_content(spending_proposal.title)
|
||||
expect(page).to have_content(spending_proposal.description)
|
||||
expect(page).to have_content(spending_proposal.author.name)
|
||||
expect(page).to have_content(spending_proposal.association_name)
|
||||
expect(page).to have_content(spending_proposal.geozone.name)
|
||||
end
|
||||
|
||||
scenario "Show (as user)" do
|
||||
user = create(:user)
|
||||
login_as(user)
|
||||
|
||||
@@ -198,6 +198,43 @@ feature 'Users' do
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
feature 'Spending proposals' do
|
||||
|
||||
background do
|
||||
@author = create(:user)
|
||||
create(:spending_proposal, author: @author, title: 'Build a school')
|
||||
end
|
||||
|
||||
scenario 'is not shown if no user logged in' do
|
||||
visit user_path(@user)
|
||||
expect(page).to_not have_content('Build a school')
|
||||
end
|
||||
|
||||
scenario 'is not shown if logged in user is a regular user' do
|
||||
login_as(create(:user))
|
||||
visit user_path(@author)
|
||||
expect(page).to_not have_content('Build a school')
|
||||
end
|
||||
|
||||
scenario 'is not shown if logged in user is moderator' do
|
||||
login_as(create(:moderator).user)
|
||||
visit user_path(@author)
|
||||
expect(page).to_not have_content('Build a school')
|
||||
end
|
||||
|
||||
scenario 'is shown if logged in user is admin' do
|
||||
login_as(create(:administrator).user)
|
||||
visit user_path(@author)
|
||||
expect(page).to have_content('Build a school')
|
||||
end
|
||||
|
||||
scenario 'is shown if logged in user is author' do
|
||||
login_as(@author)
|
||||
visit user_path(@author)
|
||||
expect(page).to have_content('Build a school')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
feature 'Special comments' do
|
||||
|
||||
Reference in New Issue
Block a user