diff --git a/app/controllers/spending_proposals_controller.rb b/app/controllers/spending_proposals_controller.rb index 1abc71549..e5bf2debf 100644 --- a/app/controllers/spending_proposals_controller.rb +++ b/app/controllers/spending_proposals_controller.rb @@ -1,7 +1,32 @@ class SpendingProposalsController < ApplicationController before_action :authenticate_user!, except: [:index] + load_and_authorize_resource + def index 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 \ No newline at end of file diff --git a/app/models/spending_proposal.rb b/app/models/spending_proposal.rb index 12fa816df..30f270ab3 100644 --- a/app/models/spending_proposal.rb +++ b/app/models/spending_proposal.rb @@ -3,14 +3,16 @@ class SpendingProposal < ActiveRecord::Base include Sanitizable include Taggable + apply_simple_captcha + belongs_to :author, -> { with_hidden }, class_name: 'User', foreign_key: 'author_id' validates :title, presence: true validates :author, presence: true validates :description, presence: true - validates :title, length: { in: 4..Proposal.title_max_length } - validates :description, length: { maximum: Proposal.description_max_length } + validates :title, length: { in: 4..SpendingProposal.title_max_length } + validates :description, length: { maximum: SpendingProposal.description_max_length } validates :terms_of_service, acceptance: { allow_nil: false }, on: :create end diff --git a/app/views/spending_proposals/_form.html.erb b/app/views/spending_proposals/_form.html.erb new file mode 100644 index 000000000..8f5bc5bb7 --- /dev/null +++ b/app/views/spending_proposals/_form.html.erb @@ -0,0 +1,52 @@ +<%= form_for(@spending_proposal, url: form_url) do |f| %> + <%= render 'shared/errors', resource: @spending_proposal %> + +
+
+ <%= 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 %> +
+ +
+ <%= f.label :description, t("spending_proposals.form.description") %> + <%= f.cktext_area :description, maxlength: SpendingProposal.description_max_length, ckeditor: { language: I18n.locale }, label: false %> +
+ +
+ <%= f.label :external_url, t("spending_proposals.form.external_url") %> + <%= f.text_field :external_url, placeholder: t("spending_proposals.form.external_url"), label: false %> +
+ +
+ <%= f.label :tag_list, t("spending_proposals.form.tags_label") %> +

<%= t("spending_proposals.form.tags_instructions") %>

+ + <% @featured_tags.each do |tag| %> + <%= tag.name %> + <% end %> + + <%= 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' %> +
+ +
+ <% if @spending_proposal.new_record? %> + <%= f.label :terms_of_service do %> + <%= f.check_box :terms_of_service, label: false %> + + <%= t("form.accept_terms", + policy: link_to(t("form.policy"), "/privacy", target: "blank"), + conditions: link_to(t("form.conditions"), "/conditions", target: "blank")).html_safe %> + + <% end %> + <% end %> +
+ +
+ <%= f.simple_captcha input_html: { required: false } %> +
+ +
+ <%= f.submit(class: "button radius", value: t("spending_proposals.form.submit_buttons.#{action_name}")) %> +
+
+<% end %> \ No newline at end of file diff --git a/app/views/spending_proposals/new.html.erb b/app/views/spending_proposals/new.html.erb new file mode 100644 index 000000000..c761487ff --- /dev/null +++ b/app/views/spending_proposals/new.html.erb @@ -0,0 +1,27 @@ +
+ +
+ <%= link_to spending_proposals_path, class: "left back" do %> + + <%= t("spending_proposals.new.back_link") %> + <% end %> +

<%= t("spending_proposals.new.start_new") %>

+
+ <%= link_to "/spending_proposals_info", target: "_blank" do %> + <%= t("spending_proposals.new.more_info")%> + <% end %> +
+ <%= render "spending_proposals/form", form_url: spending_proposals_url %> +
+ +
+ +

<%= t("spending_proposals.new.recommendations_title") %>

+ +
+ +
\ No newline at end of file diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 4e9cd5931..42c29fed8 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -37,6 +37,9 @@ en: proposal: one: "Citizen proposal" other: "Citizen proposals" + spending_proposal: + one: "Spending proposal" + other: "Spending proposals" attributes: comment: body: "Comment" diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index 998bc4fb6..780595562 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -37,6 +37,9 @@ es: proposal: one: "Propuesta ciudadana" other: "Propuestas ciudadanas" + spending_proposal: + one: "Propuesta de gasto" + other: "Propuestas de gasto" attributes: comment: body: "Comentario" diff --git a/config/locales/en.yml b/config/locales/en.yml index 40d9d4973..60032de69 100755 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -248,9 +248,27 @@ en: submit_button: "Save changes" spending_proposals: index: - title: "Citizen budget" - text: "Here you can send spending proposals to be considered in the frame of the annual citizen budgets." + title: "Participatory budgeting" + text: "Here you can send spending proposals to be considered in the frame of the annual participatory budgeting." 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: show: return_to_commentable: "Go back to " @@ -338,6 +356,7 @@ en: user: "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" + spendingproposal: "the secret code does not match the image" shared: author_info: author_deleted: "User deleted" diff --git a/config/locales/es.yml b/config/locales/es.yml index e67f42153..da8511678 100644 --- a/config/locales/es.yml +++ b/config/locales/es.yml @@ -209,7 +209,7 @@ es: 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)" 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 (',')" show: back_link: "Volver" @@ -248,9 +248,27 @@ es: submit_button: "Guardar cambios" spending_proposals: 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." 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: show: return_to_commentable: "Volver a " @@ -338,6 +356,7 @@ es: user: "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" + spendingproposal: "el código secreto no coincide con la imagen" shared: author_info: author_deleted: Usuario eliminado diff --git a/spec/features/spending_proposals_spec.rb b/spec/features/spending_proposals_spec.rb index 1a5946b01..bf4a7f585 100644 --- a/spec/features/spending_proposals_spec.rb +++ b/spec/features/spending_proposals_spec.rb @@ -8,4 +8,50 @@ feature 'Spending proposals' do expect(page).to have_link('Create spending proposal', href: new_spending_proposal_path) 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