users can create spending proposals

This commit is contained in:
Juanjo Bazán
2016-01-04 21:44:13 +01:00
parent 8b8c1feab7
commit 54badef191
9 changed files with 202 additions and 6 deletions

View File

@@ -1,7 +1,32 @@
class SpendingProposalsController < ApplicationController class SpendingProposalsController < ApplicationController
before_action :authenticate_user!, except: [:index] before_action :authenticate_user!, except: [:index]
load_and_authorize_resource
def index def index
end end
def new
@spending_proposal = SpendingProposal.new
@featured_tags = ActsAsTaggableOn::Tag.where(featured: true)
end
def create
@spending_proposal = SpendingProposal.new(spending_proposal_params)
@spending_proposal.author = current_user
if @spending_proposal.save_with_captcha
redirect_to spending_proposals_path, notice: t('flash.actions.create.notice', resource_name: t("activerecord.models.spending_proposal", count: 1))
else
@featured_tags = ActsAsTaggableOn::Tag.where(featured: true)
render :new
end
end
private
def spending_proposal_params
params.require(:spending_proposal).permit(:title, :description, :external_url, :tag_list, :terms_of_service, :captcha, :captcha_key)
end
end end

View File

@@ -3,14 +3,16 @@ class SpendingProposal < ActiveRecord::Base
include Sanitizable include Sanitizable
include Taggable include Taggable
apply_simple_captcha
belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id'
validates :title, presence: true validates :title, presence: true
validates :author, presence: true validates :author, presence: true
validates :description, presence: true validates :description, presence: true
validates :title, length: { in: 4..Proposal.title_max_length } validates :title, length: { in: 4..SpendingProposal.title_max_length }
validates :description, length: { maximum: Proposal.description_max_length } validates :description, length: { maximum: SpendingProposal.description_max_length }
validates :terms_of_service, acceptance: { allow_nil: false }, on: :create validates :terms_of_service, acceptance: { allow_nil: false }, on: :create
end end

View File

@@ -0,0 +1,52 @@
<%= form_for(@spending_proposal, url: form_url) do |f| %>
<%= render 'shared/errors', resource: @spending_proposal %>
<div class="row">
<div class="small-12 column">
<%= f.label :title, t("spending_proposals.form.title") %>
<%= f.text_field :title, maxlength: SpendingProposal.title_max_length, placeholder: t("spending_proposals.form.title"), label: false %>
</div>
<div class="ckeditor small-12 column">
<%= f.label :description, t("spending_proposals.form.description") %>
<%= f.cktext_area :description, maxlength: SpendingProposal.description_max_length, ckeditor: { language: I18n.locale }, label: false %>
</div>
<div class="small-12 column">
<%= f.label :external_url, t("spending_proposals.form.external_url") %>
<%= f.text_field :external_url, placeholder: t("spending_proposals.form.external_url"), label: false %>
</div>
<div class="small-12 column">
<%= f.label :tag_list, t("spending_proposals.form.tags_label") %>
<p class="note"><%= t("spending_proposals.form.tags_instructions") %></p>
<span class="tags">
<% @featured_tags.each do |tag| %>
<a class="js-add-tag-link"><%= tag.name %></a>
<% end %>
</span>
<%= f.text_field :tag_list, value: @spending_proposal.tag_list.to_s, label: false, placeholder: t("spending_proposals.form.tags_placeholder"), class: 'js-tag-list' %>
</div>
<div class="small-12 column">
<% if @spending_proposal.new_record? %>
<%= f.label :terms_of_service do %>
<%= f.check_box :terms_of_service, label: false %>
<span class="checkbox">
<%= t("form.accept_terms",
policy: link_to(t("form.policy"), "/privacy", target: "blank"),
conditions: link_to(t("form.conditions"), "/conditions", target: "blank")).html_safe %>
</span>
<% end %>
<% end %>
</div>
<div class="small-12 column">
<%= f.simple_captcha input_html: { required: false } %>
</div>
<div class="actions small-12 column">
<%= f.submit(class: "button radius", value: t("spending_proposals.form.submit_buttons.#{action_name}")) %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,27 @@
<div class="spending-proposal-new row">
<div class="small-12 medium-9 column">
<%= link_to spending_proposals_path, class: "left back" do %>
<i class="icon-angle-left left"></i>
<%= t("spending_proposals.new.back_link") %>
<% end %>
<h1><%= t("spending_proposals.new.start_new") %></h1>
<div class="alert-box info radius">
<%= link_to "/spending_proposals_info", target: "_blank" do %>
<%= t("spending_proposals.new.more_info")%>
<% end %>
</div>
<%= render "spending_proposals/form", form_url: spending_proposals_url %>
</div>
<div class="small-12 medium-3 column">
<i class="icon-spending-proposals right"></i>
<h2><%= t("spending_proposals.new.recommendations_title") %></h2>
<ul class="recommendations">
<li><%= t("spending_proposals.new.recommendation_one") %></li>
<li><%= t("spending_proposals.new.recommendation_two") %></li>
<li><%= t("spending_proposals.new.recommendation_three") %></li>
</ul>
</div>
</div>

View File

@@ -37,6 +37,9 @@ en:
proposal: proposal:
one: "Citizen proposal" one: "Citizen proposal"
other: "Citizen proposals" other: "Citizen proposals"
spending_proposal:
one: "Spending proposal"
other: "Spending proposals"
attributes: attributes:
comment: comment:
body: "Comment" body: "Comment"

View File

@@ -37,6 +37,9 @@ es:
proposal: proposal:
one: "Propuesta ciudadana" one: "Propuesta ciudadana"
other: "Propuestas ciudadanas" other: "Propuestas ciudadanas"
spending_proposal:
one: "Propuesta de gasto"
other: "Propuestas de gasto"
attributes: attributes:
comment: comment:
body: "Comentario" body: "Comentario"

View File

@@ -248,9 +248,27 @@ en:
submit_button: "Save changes" submit_button: "Save changes"
spending_proposals: spending_proposals:
index: index:
title: "Citizen budget" title: "Participatory budgeting"
text: "Here you can send spending proposals to be considered in the frame of the annual citizen budgets." text: "Here you can send spending proposals to be considered in the frame of the annual participatory budgeting."
create_link: "Create spending proposal" create_link: "Create spending proposal"
new:
back_link: Back
start_new: "Create spending proposal"
more_info: "How do participatory bufgeting works?"
recommendations_title: "Recommendations for creating a spending proposal"
recommendation_one: "It's mandatory that the proposal makes reference to a budgetable action."
recommendation_two: "Any proposal or comment suggesting illegal action will be deleted."
recommendation_three: "Try to go into details when describing your spending proposal so the reviewing team undertands your points."
form:
title: "Spending proposal title"
description: "Description"
external_url: "Link to additional documentation"
tags_label: "Tags"
tags_instructions: "Tag this spending proposal. You can choose from our tags or add your own."
tags_placeholder: "Enter the tags you would like to use, separated by commas (',')"
submit_buttons:
new: Create
create: Create
comments: comments:
show: show:
return_to_commentable: "Go back to " return_to_commentable: "Go back to "
@@ -338,6 +356,7 @@ en:
user: "the secret code does not match the image" user: "the secret code does not match the image"
debate: "the secret code does not match the image" debate: "the secret code does not match the image"
proposal: "the secret code does not match the image" proposal: "the secret code does not match the image"
spendingproposal: "the secret code does not match the image"
shared: shared:
author_info: author_info:
author_deleted: "User deleted" author_deleted: "User deleted"

View File

@@ -209,7 +209,7 @@ es:
proposal_responsible_name: "Nombre y apellidos de la persona que hace esta propuesta" proposal_responsible_name: "Nombre y apellidos de la persona que hace esta propuesta"
proposal_responsible_name_note: "(individualmente o como representante de un colectivo; no se mostrará públicamente)" proposal_responsible_name_note: "(individualmente o como representante de un colectivo; no se mostrará públicamente)"
tags_label: "Temas" tags_label: "Temas"
tags_instructions: "Etiqueta esta propuesta. Puedes elegir entre nuestras propuestas o introducir las que desees." tags_instructions: "Etiqueta esta propuesta. Puedes elegir entre nuestras sugerencias o introducir las que desees."
tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')" tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')"
show: show:
back_link: "Volver" back_link: "Volver"
@@ -248,9 +248,27 @@ es:
submit_button: "Guardar cambios" submit_button: "Guardar cambios"
spending_proposals: spending_proposals:
index: index:
title: "Presupuestos ciudadanos" title: "Presupuestos participativos"
text: "Desde esta sección podrás sugerir propuestas de gasto que irán asociadas a las partidas de presupuestos ciudadanos. El requisito principal es que sean propuestas presupuestables." text: "Desde esta sección podrás sugerir propuestas de gasto que irán asociadas a las partidas de presupuestos ciudadanos. El requisito principal es que sean propuestas presupuestables."
create_link: "Enviar propuesta de gasto" create_link: "Enviar propuesta de gasto"
new:
back_link: Volver
start_new: "Crear una propuesta de gasto"
more_info: "¿Cómo funcionan los presupuestos participativos?"
recommendations_title: "Recomendaciones para crear una propuesta de gasto"
recommendation_one: "Es fundamental que haga referencia a una actuación presupuestable."
recommendation_two: "Cualquier propuesta o comentario que implique acciones ilegales será eliminada."
recommendation_three: "Intenta detallar lo máximo posible la propuesta para que el equipo de gobierno encargado de estudiarla tenga las menor dudas posibles."
form:
title: "Título de la propuesta de gasto"
description: "Descripción detallada"
external_url: "Enlace a documentación adicional"
tags_label: "Temas"
tags_instructions: "Etiqueta esta propuesta de gasto. Puedes elegir entre nuestras sugerencias o introducir las que desees."
tags_placeholder: "Escribe las etiquetas que desees separadas por una coma (',')"
submit_buttons:
new: Crear
create: Crear
comments: comments:
show: show:
return_to_commentable: "Volver a " return_to_commentable: "Volver a "
@@ -338,6 +356,7 @@ es:
user: "el código secreto no coincide con la imagen" user: "el código secreto no coincide con la imagen"
debate: "el código secreto no coincide con la imagen" debate: "el código secreto no coincide con la imagen"
proposal: "el código secreto no coincide con la imagen" proposal: "el código secreto no coincide con la imagen"
spendingproposal: "el código secreto no coincide con la imagen"
shared: shared:
author_info: author_info:
author_deleted: Usuario eliminado author_deleted: Usuario eliminado

View File

@@ -8,4 +8,50 @@ feature 'Spending proposals' do
expect(page).to have_link('Create spending proposal', href: new_spending_proposal_path) expect(page).to have_link('Create spending proposal', href: new_spending_proposal_path)
end end
scenario 'Create' do
author = create(:user)
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_captcha', with: correct_captcha_text
check 'spending_proposal_terms_of_service'
click_button 'Create'
expect(page).to have_content 'Spending proposal created successfully'
end
scenario 'Captcha is required for proposal creation' do
login_as(create(:user))
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_captcha', with: 'wrongText'
check 'spending_proposal_terms_of_service'
click_button 'Create'
expect(page).to_not have_content 'Spending proposal created successfully'
expect(page).to have_content '1 error'
fill_in 'spending_proposal_captcha', with: correct_captcha_text
click_button 'Create'
expect(page).to have_content 'Spending proposal created successfully'
end
scenario 'Errors on create' do
author = create(:user)
login_as(author)
visit new_spending_proposal_path
click_button 'Create'
expect(page).to have_content error_message
end
end end