Merge pull request #590 from AyuntamientoMadrid/management-proposals
Management proposals
This commit is contained in:
52
app/controllers/management/proposals_controller.rb
Normal file
52
app/controllers/management/proposals_controller.rb
Normal file
@@ -0,0 +1,52 @@
|
||||
class Management::ProposalsController < Management::BaseController
|
||||
include HasOrders
|
||||
include CommentableActions
|
||||
|
||||
before_action :check_verified_user, except: :print
|
||||
before_action :set_proposal, only: :vote
|
||||
before_action :parse_search_terms, only: :index
|
||||
|
||||
has_orders %w{hot_score confidence_score created_at most_commented random}, only: [:index, :print]
|
||||
|
||||
def vote
|
||||
@proposal.register_vote(current_user, 'yes')
|
||||
set_proposal_votes(@proposal)
|
||||
end
|
||||
|
||||
def print
|
||||
@proposals = Proposal.all.page(params[:page]).for_render.send("sort_by_#{@current_order}")
|
||||
set_proposal_votes(@proposal)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def set_proposal
|
||||
@proposal = Proposal.find(params[:id])
|
||||
end
|
||||
|
||||
def proposal_params
|
||||
params.require(:proposal).permit(:title, :question, :summary, :description, :external_url, :video_url, :responsible_name, :tag_list, :terms_of_service, :captcha, :captcha_key)
|
||||
end
|
||||
|
||||
def current_user
|
||||
#CHANGE ME
|
||||
#Should be user being managed
|
||||
User.last
|
||||
end
|
||||
|
||||
def resource_model
|
||||
Proposal
|
||||
end
|
||||
|
||||
def check_verified_user
|
||||
unless current_user.level_two_or_three_verified?
|
||||
redirect_to management_root_path, alert: t("management.proposals.alert.unverified_user")
|
||||
end
|
||||
end
|
||||
|
||||
#Duplicated in application_controller. Move to a concenrn.
|
||||
def set_proposal_votes(proposals)
|
||||
@proposal_votes = current_user ? current_user.proposal_votes(proposals) : {}
|
||||
end
|
||||
|
||||
end
|
||||
10
app/views/admin/shared/_proposal_search.html.erb
Normal file
10
app/views/admin/shared/_proposal_search.html.erb
Normal file
@@ -0,0 +1,10 @@
|
||||
<%= form_for(Proposal.new, url: url, as: :proposal, method: :get) do |f| %>
|
||||
<div class="row">
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= text_field_tag :search, "", placeholder: t("admin.shared.proposal_search.placeholder") %>
|
||||
</div>
|
||||
<div class="form-inline small-12 medium-6 column">
|
||||
<%= f.submit t("admin.shared.proposal_search.button"), class: "button radius success" %>
|
||||
</div>
|
||||
</div>
|
||||
<% end %>
|
||||
1
app/views/management/proposals/_proposal.html.erb
Normal file
1
app/views/management/proposals/_proposal.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= render partial: 'proposals/proposal', locals: {proposal: proposal} %>
|
||||
2
app/views/management/proposals/_votes.html.erb
Normal file
2
app/views/management/proposals/_votes.html.erb
Normal file
@@ -0,0 +1,2 @@
|
||||
<%= render 'proposals/votes',
|
||||
{ proposal: proposal, vote_url: vote_management_proposal_path(proposal, value: 'yes') } %>
|
||||
22
app/views/management/proposals/index.html.erb
Normal file
22
app/views/management/proposals/index.html.erb
Normal file
@@ -0,0 +1,22 @@
|
||||
<section role="main">
|
||||
<%= render 'admin/shared/proposal_search', url: management_proposals_path %>
|
||||
|
||||
<div class="wrap row">
|
||||
<div id="proposals" class="proposals-list small-12 medium-9 column">
|
||||
|
||||
<div class="filters">
|
||||
<div class="small-12 medium-7 left">
|
||||
<% if @search_terms %>
|
||||
<h2 class="margin-top">
|
||||
<%= page_entries_info @proposals %>
|
||||
<%= t("proposals.index.search_results", count: @proposals.size, search_term: @search_terms) %>
|
||||
</h2>
|
||||
<% end %>
|
||||
</div>
|
||||
|
||||
<%= render @proposals %>
|
||||
<%= paginate @proposals %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
7
app/views/management/proposals/new.html.erb
Normal file
7
app/views/management/proposals/new.html.erb
Normal file
@@ -0,0 +1,7 @@
|
||||
<div class="proposal-new row">
|
||||
|
||||
<div class="small-12 medium-9 column">
|
||||
<%= render "proposals/form", form_url: management_proposals_url %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
35
app/views/management/proposals/print.html.erb
Normal file
35
app/views/management/proposals/print.html.erb
Normal file
@@ -0,0 +1,35 @@
|
||||
<section id="printme" role="main">
|
||||
<a id="print_link" onclick="print();" class="button warning radius">
|
||||
<%= t('management.proposals.print.print_button') %>
|
||||
</a>
|
||||
<div class="wrap row">
|
||||
<div id="proposals" class="proposals-list small-12 medium-9 column">
|
||||
|
||||
<div class="filters">
|
||||
<div class="small-12 medium-7 left">
|
||||
<div class="small-12 inline-block">
|
||||
<h2 class="inline-block">
|
||||
<%= t("proposals.index.select_order_long") %>
|
||||
</h2>
|
||||
<%= render 'shared/order_selector', i18n_namespace: "proposals.index" %>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<%= render @proposals %>
|
||||
<%= paginate @proposals %>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
function print(){
|
||||
var object=document.getElementById('printme');
|
||||
var browser=window.open('','_blank');
|
||||
browser.document.write(object.innerHTML);
|
||||
browser.document.close();
|
||||
browser.print();
|
||||
browser.close();
|
||||
}
|
||||
</script>
|
||||
1
app/views/management/proposals/vote.js.erb
Normal file
1
app/views/management/proposals/vote.js.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= render template: 'proposals/vote' %>
|
||||
@@ -1,4 +1,4 @@
|
||||
<%= form_for(@proposal) do |f| %>
|
||||
<%= form_for(@proposal, url: form_url) do |f| %>
|
||||
<%= render 'shared/errors', resource: @proposal %>
|
||||
|
||||
<div class="row">
|
||||
|
||||
@@ -47,7 +47,8 @@
|
||||
</div>
|
||||
|
||||
<div id="<%= dom_id(proposal) %>_votes" class="small-12 medium-3 column text-center">
|
||||
<%= render 'proposals/votes', proposal: proposal %>
|
||||
<%= render 'votes',
|
||||
{ proposal: proposal, vote_url: vote_proposal_path(proposal, value: 'yes') } %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
<%= t("proposals.proposal.already_supported") %>
|
||||
</div>
|
||||
<% else %>
|
||||
<%= link_to vote_proposal_path(proposal, value: 'yes'),
|
||||
<%= link_to vote_url,
|
||||
class: "button button-support tiny radius expand",
|
||||
title: t('proposals.proposal.support_title'), method: "post", remote: true do %>
|
||||
<%= t("proposals.proposal.support") %>
|
||||
|
||||
@@ -12,6 +12,6 @@
|
||||
|
||||
<h1><%= t("proposals.edit.editing") %></h1>
|
||||
|
||||
<%= render "form" %>
|
||||
<%= render "form", form_url: proposal_url(@proposal) %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
<%= link_to t("proposals.index.start_proposal"), new_proposal_path, class: 'button radius expand' %>
|
||||
</div>
|
||||
|
||||
<%= render @proposals %>
|
||||
<%= render partial: 'proposals/proposal', collection: @proposals %>
|
||||
<%= paginate @proposals %>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
<%= t("proposals.new.more_info")%>
|
||||
<% end %>
|
||||
</div>
|
||||
<%= render "form" %>
|
||||
<%= render "proposals/form", form_url: proposals_url %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 medium-3 column">
|
||||
|
||||
@@ -97,7 +97,8 @@
|
||||
<h3><%= t("votes.supports") %></h3>
|
||||
<div class="text-center">
|
||||
<div id="<%= dom_id(@proposal) %>_votes">
|
||||
<%= render 'proposals/votes', proposal: @proposal %>
|
||||
<%= render 'votes',
|
||||
{ proposal: @proposal, vote_url: vote_proposal_path(@proposal, value: 'yes') } %>
|
||||
</div>
|
||||
</div>
|
||||
<div class="sidebar-divider"></div>
|
||||
|
||||
2
app/views/welcome/_votes.html.erb
Normal file
2
app/views/welcome/_votes.html.erb
Normal file
@@ -0,0 +1,2 @@
|
||||
<%= render 'proposals/votes',
|
||||
{ proposal: proposal, vote_url: vote_proposal_path(proposal, value: 'yes') } %>
|
||||
@@ -26,6 +26,9 @@ en:
|
||||
user_search:
|
||||
placeholder: 'Search user by name or email'
|
||||
button: 'Search'
|
||||
proposal_search:
|
||||
placeholder: 'Search proposals by title, description or question'
|
||||
button: 'Search'
|
||||
organizations:
|
||||
index:
|
||||
title: Organizations
|
||||
|
||||
@@ -26,6 +26,9 @@ es:
|
||||
user_search:
|
||||
placeholder: 'Buscar usuario por nombre o email'
|
||||
button: 'Buscar'
|
||||
proposal_search:
|
||||
placeholder: 'Buscar propuestas por título, descripción o pregunta'
|
||||
button: 'Buscar'
|
||||
organizations:
|
||||
index:
|
||||
title: Organizaciones
|
||||
|
||||
@@ -12,6 +12,11 @@ en:
|
||||
dashboard:
|
||||
index:
|
||||
title: "Management"
|
||||
proposals:
|
||||
print:
|
||||
print_button: Print
|
||||
alert:
|
||||
unverified_user: User is not verified
|
||||
permissions:
|
||||
debates: "Engage in debates"
|
||||
create_proposals: "Create proposals"
|
||||
|
||||
@@ -11,7 +11,12 @@ es:
|
||||
users: "Usuarios"
|
||||
dashboard:
|
||||
index:
|
||||
title: "Gestión"
|
||||
title: "Gestión"
|
||||
proposals:
|
||||
print:
|
||||
print_button: Imprimir
|
||||
alert:
|
||||
unverified_user: Este usuario no está verificado
|
||||
permissions:
|
||||
debates: "Participar en debates"
|
||||
create_proposals: "Crear nuevas propuestas"
|
||||
|
||||
@@ -185,6 +185,15 @@ Rails.application.routes.draw do
|
||||
get 'sign_in', to: 'sessions#create'
|
||||
|
||||
resources :sessions, only: :create
|
||||
resources :proposals, only: [:index, :new, :create] do
|
||||
member do
|
||||
post :vote
|
||||
end
|
||||
|
||||
collection do
|
||||
get :print
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Example of regular route:
|
||||
|
||||
141
spec/features/management/proposals_spec.rb
Normal file
141
spec/features/management/proposals_spec.rb
Normal file
@@ -0,0 +1,141 @@
|
||||
require 'rails_helper'
|
||||
|
||||
feature 'Proposals' do
|
||||
|
||||
background do
|
||||
manager = create(:manager)
|
||||
login_as_manager(manager)
|
||||
end
|
||||
|
||||
context "Create" do
|
||||
|
||||
scenario 'Creating proposals on behalf of someone' do
|
||||
user = create(:user, :level_two)
|
||||
login_managed_user(user)
|
||||
|
||||
visit new_management_proposal_path
|
||||
|
||||
fill_in 'proposal_title', with: 'Help refugees'
|
||||
fill_in 'proposal_question', with: '¿Would you like to give assistance to war refugees?'
|
||||
fill_in 'proposal_summary', with: 'In summary, what we want is...'
|
||||
fill_in 'proposal_description', with: 'This is very important because...'
|
||||
fill_in 'proposal_external_url', with: 'http://rescue.org/refugees'
|
||||
fill_in 'proposal_video_url', with: 'http://youtube.com'
|
||||
fill_in 'proposal_captcha', with: correct_captcha_text
|
||||
check 'proposal_terms_of_service'
|
||||
|
||||
click_button 'Start a proposal'
|
||||
|
||||
expect(page).to have_content 'Proposal was successfully created.'
|
||||
|
||||
expect(page).to have_content 'Help refugees'
|
||||
expect(page).to have_content '¿Would you like to give assistance to war refugees?'
|
||||
expect(page).to have_content 'In summary, what we want is...'
|
||||
expect(page).to have_content 'This is very important because...'
|
||||
expect(page).to have_content 'http://rescue.org/refugees'
|
||||
expect(page).to have_content 'http://youtube.com'
|
||||
expect(page).to have_content user.name
|
||||
expect(page).to have_content I18n.l(Proposal.last.created_at.to_date)
|
||||
end
|
||||
|
||||
scenario "Should not allow unverified users to create proposals" do
|
||||
user = create(:user)
|
||||
login_managed_user(user)
|
||||
|
||||
visit new_management_proposal_path
|
||||
|
||||
expect(page).to have_content "User is not verified"
|
||||
end
|
||||
end
|
||||
|
||||
context "Voting" do
|
||||
|
||||
scenario 'Voting proposals on behalf of someone', :js do
|
||||
proposal = create(:proposal)
|
||||
|
||||
user = create(:user, :level_two)
|
||||
login_managed_user(user)
|
||||
|
||||
visit management_proposals_path
|
||||
|
||||
within("#proposals") do
|
||||
find('.in-favor a').click
|
||||
|
||||
expect(page).to have_content "1 support"
|
||||
expect(page).to have_content "You already supported this proposal"
|
||||
end
|
||||
expect(URI.parse(current_url).path).to eq(management_proposals_path)
|
||||
end
|
||||
|
||||
scenario "Should not allow unverified users to vote proposals" do
|
||||
proposal = create(:proposal)
|
||||
|
||||
user = create(:user)
|
||||
login_managed_user(user)
|
||||
|
||||
visit management_proposals_path
|
||||
|
||||
expect(page).to have_content "User is not verified"
|
||||
end
|
||||
|
||||
scenario "Searching" do
|
||||
proposal1 = create(:proposal, title: "Show me what you got")
|
||||
proposal2 = create(:proposal, title: "Get Schwifty")
|
||||
|
||||
user = create(:user, :level_two)
|
||||
login_managed_user(user)
|
||||
|
||||
visit management_proposals_path
|
||||
|
||||
fill_in "search", with: "what you got"
|
||||
click_button "Search"
|
||||
|
||||
expect(current_path).to eq(management_proposals_path)
|
||||
|
||||
within("#proposals") do
|
||||
expect(page).to have_css('.proposal', count: 1)
|
||||
expect(page).to have_content(proposal1.title)
|
||||
expect(page).to_not have_content(proposal2.title)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
context "Printing" do
|
||||
scenario 'Printing proposals', :js do
|
||||
5.times { create(:proposal) }
|
||||
|
||||
visit print_management_proposals_path
|
||||
|
||||
find("#print_link").click
|
||||
|
||||
### CHANGE ME
|
||||
# should probably test something else here
|
||||
# maybe that we are loading a print.css stylesheet?
|
||||
###
|
||||
end
|
||||
|
||||
scenario "Filtering proposals to be printed", :js do
|
||||
create(:proposal, title: 'Best proposal').update_column(:confidence_score, 10)
|
||||
create(:proposal, title: 'Worst proposal').update_column(:confidence_score, 2)
|
||||
create(:proposal, title: 'Medium proposal').update_column(:confidence_score, 5)
|
||||
|
||||
user = create(:user, :level_two)
|
||||
login_managed_user(user)
|
||||
|
||||
visit print_management_proposals_path
|
||||
|
||||
select 'most supported', from: 'order-selector'
|
||||
|
||||
expect(page).to have_selector('.js-order-selector[data-order="confidence_score"]')
|
||||
|
||||
within '#proposals' do
|
||||
expect('Best proposal').to appear_before('Medium proposal')
|
||||
expect('Medium proposal').to appear_before('Worst proposal')
|
||||
end
|
||||
|
||||
expect(current_url).to include('order=confidence_score')
|
||||
expect(current_url).to include('page=1')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
@@ -28,6 +28,17 @@ module CommonActions
|
||||
click_button 'Log in'
|
||||
end
|
||||
|
||||
def login_as_manager(manager)
|
||||
visit management_sign_in_path(login: manager.username, clave_usuario: manager.password)
|
||||
end
|
||||
|
||||
def login_managed_user(user)
|
||||
####
|
||||
# CHANGE ME
|
||||
# Should identify the user being managed
|
||||
####
|
||||
end
|
||||
|
||||
def confirm_email
|
||||
expect(page).to have_content "A message with a confirmation link has been sent to your email address."
|
||||
|
||||
|
||||
Reference in New Issue
Block a user