From 822140a147411ffcc79f144ae56f81a3ea550c5e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Wed, 26 May 2021 11:24:27 +0200 Subject: [PATCH 1/5] Move systems specs to budget component As they are much faster. --- .../budgets/budget_component_spec.rb | 115 ++++++++++++++++++ spec/system/budgets/budgets_spec.rb | 98 --------------- 2 files changed, 115 insertions(+), 98 deletions(-) create mode 100644 spec/components/budgets/budget_component_spec.rb diff --git a/spec/components/budgets/budget_component_spec.rb b/spec/components/budgets/budget_component_spec.rb new file mode 100644 index 000000000..f25820bb1 --- /dev/null +++ b/spec/components/budgets/budget_component_spec.rb @@ -0,0 +1,115 @@ +require "rails_helper" + +describe Budgets::BudgetComponent, type: :component do + let(:budget) { create(:budget) } + let(:heading) { create(:budget_heading, budget: budget) } + let(:user) { create(:user) } + + before do + allow(controller).to receive(:current_user).and_return(user) + end + + describe "budget header" do + it "shows budget name and link to help" do + budget.update!(phase: "informing") + + render_inline Budgets::BudgetComponent.new(budget) + + within(".budget-header") do + expect(page).to have_content(budget.name) + expect(page).to have_content(budget.description) + expect(page).to have_link("Help with participatory budgets") + end + end + end + + describe "map" do + before do + Setting["feature.map"] = true + end + + it "displays investment's map location markers" do + investment1 = create(:budget_investment, heading: heading) + investment2 = create(:budget_investment, heading: heading) + investment3 = create(:budget_investment, heading: heading) + + create(:map_location, longitude: 40.1234, latitude: -3.634, investment: investment1) + create(:map_location, longitude: 40.1235, latitude: -3.635, investment: investment2) + create(:map_location, longitude: 40.1236, latitude: -3.636, investment: investment3) + + render_inline Budgets::BudgetComponent.new(budget) + + within ".map_location" do + expect(page).to have_css(".map-icon", count: 3) + end + end + + it "displays all investment's map location if there are no selected" do + budget.update!(phase: :publishing_prices) + + investment1 = create(:budget_investment, heading: heading) + investment2 = create(:budget_investment, heading: heading) + investment3 = create(:budget_investment, heading: heading) + investment4 = create(:budget_investment, heading: heading) + + investment1.create_map_location(longitude: 40.1234, latitude: 3.1234, zoom: 10) + investment2.create_map_location(longitude: 40.1235, latitude: 3.1235, zoom: 10) + investment3.create_map_location(longitude: 40.1236, latitude: 3.1236, zoom: 10) + investment4.create_map_location(longitude: 40.1240, latitude: 3.1240, zoom: 10) + + render_inline Budgets::BudgetComponent.new(budget) + + within ".map_location" do + expect(page).to have_css(".map-icon", count: 4) + end + end + + it "displays only selected investment's map location from publishing prices phase" do + budget.update!(phase: :publishing_prices) + + investment1 = create(:budget_investment, :selected, heading: heading) + investment2 = create(:budget_investment, :selected, heading: heading) + investment3 = create(:budget_investment, heading: heading) + investment4 = create(:budget_investment, heading: heading) + + investment1.create_map_location(longitude: 40.1234, latitude: 3.1234, zoom: 10) + investment2.create_map_location(longitude: 40.1235, latitude: 3.1235, zoom: 10) + investment3.create_map_location(longitude: 40.1236, latitude: 3.1236, zoom: 10) + investment4.create_map_location(longitude: 40.1240, latitude: 3.1240, zoom: 10) + + render_inline Budgets::BudgetComponent.new(budget) + + within ".map_location" do + expect(page).to have_css(".map-icon", count: 2) + end + end + + scenario "skips invalid map markers" do + map_locations = [] + + investment = create(:budget_investment, heading: heading) + + map_locations << { longitude: 40.123456789, latitude: 3.12345678 } + map_locations << { longitude: 40.123456789, latitude: "********" } + map_locations << { longitude: "**********", latitude: 3.12345678 } + + coordinates = map_locations.map do |map_location| + { + lat: map_location[:latitude], + long: map_location[:longitude], + investment_title: investment.title, + investment_id: investment.id, + budget_id: budget.id + } + end + + allow_any_instance_of(Budgets::BudgetComponent).to receive(:coordinates).and_return(coordinates) + + render_inline Budgets::BudgetComponent.new(budget) + + within ".map_location" do + expect(page).to have_css(".map-icon", count: 1) + end + end + end +end diff --git a/spec/system/budgets/budgets_spec.rb b/spec/system/budgets/budgets_spec.rb index 685d2d14d..d84ef68cf 100644 --- a/spec/system/budgets/budgets_spec.rb +++ b/spec/system/budgets/budgets_spec.rb @@ -27,12 +27,6 @@ describe "Budgets" do visit budgets_path - within(".budget-header") do - expect(page).to have_content(budget.name) - expect(page).to have_content(budget.description) - expect(page).to have_link("Help with participatory budgets") - end - within(".budget-subheader") do expect(page).to have_content "CURRENT PHASE" expect(page).to have_content "Information" @@ -228,98 +222,6 @@ describe "Budgets" do expect(page).to have_css(".tabs-panel.is-active", count: 1) end - context "Index map" do - let(:heading) { create(:budget_heading, budget: budget) } - - before do - Setting["feature.map"] = true - end - - scenario "Display investment's map location markers" do - investment1 = create(:budget_investment, heading: heading) - investment2 = create(:budget_investment, heading: heading) - investment3 = create(:budget_investment, heading: heading) - - create(:map_location, longitude: 40.1234, latitude: -3.634, investment: investment1) - create(:map_location, longitude: 40.1235, latitude: -3.635, investment: investment2) - create(:map_location, longitude: 40.1236, latitude: -3.636, investment: investment3) - - visit budgets_path - - within ".map_location" do - expect(page).to have_css(".map-icon", count: 3, visible: :all) - end - end - - scenario "Display all investment's map location if there are no selected" do - budget.update!(phase: :publishing_prices) - - investment1 = create(:budget_investment, heading: heading) - investment2 = create(:budget_investment, heading: heading) - investment3 = create(:budget_investment, heading: heading) - investment4 = create(:budget_investment, heading: heading) - - investment1.create_map_location(longitude: 40.1234, latitude: 3.1234, zoom: 10) - investment2.create_map_location(longitude: 40.1235, latitude: 3.1235, zoom: 10) - investment3.create_map_location(longitude: 40.1236, latitude: 3.1236, zoom: 10) - investment4.create_map_location(longitude: 40.1240, latitude: 3.1240, zoom: 10) - - visit budgets_path - - within ".map_location" do - expect(page).to have_css(".map-icon", count: 4, visible: :all) - end - end - - scenario "Display only selected investment's map location from publishing prices phase" do - budget.update!(phase: :publishing_prices) - - investment1 = create(:budget_investment, :selected, heading: heading) - investment2 = create(:budget_investment, :selected, heading: heading) - investment3 = create(:budget_investment, heading: heading) - investment4 = create(:budget_investment, heading: heading) - - investment1.create_map_location(longitude: 40.1234, latitude: 3.1234, zoom: 10) - investment2.create_map_location(longitude: 40.1235, latitude: 3.1235, zoom: 10) - investment3.create_map_location(longitude: 40.1236, latitude: 3.1236, zoom: 10) - investment4.create_map_location(longitude: 40.1240, latitude: 3.1240, zoom: 10) - - visit budgets_path - - within ".map_location" do - expect(page).to have_css(".map-icon", count: 2, visible: :all) - end - end - - scenario "Skip invalid map markers" do - map_locations = [] - - investment = create(:budget_investment, heading: heading) - - map_locations << { longitude: 40.123456789, latitude: 3.12345678 } - map_locations << { longitude: 40.123456789, latitude: "********" } - map_locations << { longitude: "**********", latitude: 3.12345678 } - - coordinates = map_locations.map do |map_location| - { - lat: map_location[:latitude], - long: map_location[:longitude], - investment_title: investment.title, - investment_id: investment.id, - budget_id: budget.id - } - end - - allow_any_instance_of(Budgets::BudgetComponent).to receive(:coordinates).and_return(coordinates) - - visit budgets_path - - within ".map_location" do - expect(page).to have_css(".map-icon", count: 1, visible: :all) - end - end - end - context "Show" do let!(:budget) { create(:budget, :selecting) } let!(:group) { create(:budget_group, budget: budget) } From 26d14cbd04a8f1521afb2e593b589f71a46dc33c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sen=C3=A9n=20Rodero=20Rodr=C3=ADguez?= Date: Wed, 26 May 2021 11:34:40 +0200 Subject: [PATCH 2/5] Move system specs to subheader component specs As the are much faster. Keep a system spec to check the component is called from the view. --- .../budgets/subheader_component_spec.rb | 104 ++++++++++++++++++ spec/system/budgets/budgets_spec.rb | 76 +------------ 2 files changed, 106 insertions(+), 74 deletions(-) create mode 100644 spec/components/budgets/subheader_component_spec.rb diff --git a/spec/components/budgets/subheader_component_spec.rb b/spec/components/budgets/subheader_component_spec.rb new file mode 100644 index 000000000..0bae1f7c6 --- /dev/null +++ b/spec/components/budgets/subheader_component_spec.rb @@ -0,0 +1,104 @@ +require "rails_helper" + +describe Budgets::SubheaderComponent, type: :component do + it "shows budget current phase name" do + allow(controller).to receive(:current_user).and_return(create(:user)) + budget = create(:budget, :informing) + + render_inline Budgets::SubheaderComponent.new(budget) + + within(".budget-subheader") do + expect(page).to have_content "CURRENT PHASE" + expect(page).to have_content "Information" + end + end + + describe "when budget is accepting" do + let(:budget) { create(:budget, :accepting) } + + it "and user is level_two_or_three_verified shows a link to create a new investment" do + allow(controller).to receive(:current_user).and_return(create(:user, :level_two)) + + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).to have_link "Create a budget investment" + + (Budget::Phase::PHASE_KINDS - ["accepting"]).each do |phase| + budget.update!(phase: phase) + budget.reload + + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).not_to have_link "Create a budget investment" + end + end + + it "and user is not verified shows a link to account verification" do + allow(controller).to receive(:current_user).and_return(create(:user)) + + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).to have_content "To create a new budget investment" + expect(page).to have_link "verify your account" + + (Budget::Phase::PHASE_KINDS - ["accepting"]).each do |phase| + budget.update!(phase: phase) + budget.reload + + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).not_to have_content "To create a new budget investment" + expect(page).not_to have_link "verify your account" + end + end + + it "and user is not logged in shows links to sign in and sign up" do + allow(controller).to receive(:current_user).and_return(nil) + + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).to have_content "To create a new budget investment you must" + expect(page).to have_link "sign in" + expect(page).to have_link "sign up" + + (Budget::Phase::PHASE_KINDS - ["accepting"]).each do |phase| + budget.update!(phase: phase) + budget.reload + + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).not_to have_content "To create a new budget investment you must" + expect(page).not_to have_link "sign in" + expect(page).not_to have_link "sign up" + end + end + end + + describe "See results link" do + it "is showed when budget is finished and results are enabled for all users" do + budget = create(:budget, :finished) + allow(controller).to receive(:current_user).and_return(create(:user)) + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).to have_link "See results" + + allow(controller).to receive(:current_user).and_return(create(:administrator).user) + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).to have_link "See results" + end + + it "is not showed when budget is finished or results are disabled for all users" do + budget = create(:budget, :balloting, results_enabled: true) + allow(controller).to receive(:current_user).and_return(create(:user)) + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).not_to have_link "See results" + + allow(controller).to receive(:current_user).and_return(create(:administrator).user) + render_inline Budgets::SubheaderComponent.new(budget) + + expect(page).not_to have_link "See results" + end + end +end diff --git a/spec/system/budgets/budgets_spec.rb b/spec/system/budgets/budgets_spec.rb index d84ef68cf..e851c0c19 100644 --- a/spec/system/budgets/budgets_spec.rb +++ b/spec/system/budgets/budgets_spec.rb @@ -22,17 +22,6 @@ describe "Budgets" do let!(:heading1) { create(:budget_heading, group: group1) } let!(:heading2) { create(:budget_heading, group: group2) } - scenario "Show normal index with links in informing phase" do - budget.update!(phase: "informing") - - visit budgets_path - - within(".budget-subheader") do - expect(page).to have_content "CURRENT PHASE" - expect(page).to have_content "Information" - end - end - scenario "Show normal index with links publishing prices" do budget.update!(phase: "publishing_prices") @@ -137,15 +126,6 @@ describe "Budgets" do expect(page).to have_content "There are no budgets" end - - scenario "Accepting" do - budget.update!(phase: "accepting") - login_as(create(:user, :level_two)) - - visit budgets_path - - expect(page).to have_link "Create a budget investment" - end end scenario "Index shows only published phases" do @@ -281,36 +261,14 @@ describe "Budgets" do expect(page).not_to have_css("#budget_heading_#{heading4.id}") end - scenario "See results button is showed if the budget has finished for all users" do + scenario "See results button is showed if the budget has finished" do user = create(:user) - admin = create(:administrator) budget = create(:budget, :finished) login_as(user) visit budget_path(budget) + expect(page).to have_link "See results" - - logout - - login_as(admin.user) - visit budget_path(budget) - expect(page).to have_link "See results" - end - - scenario "See results button isn't showed if the budget hasn't finished for all users" do - user = create(:user) - admin = create(:administrator) - budget = create(:budget, :balloting) - - login_as(user) - visit budget_path(budget) - expect(page).not_to have_link "See results" - - logout - - login_as(admin.user) - visit budget_path(budget) - expect(page).not_to have_link "See results" end end @@ -328,34 +286,4 @@ describe "Budgets" do end end end - - context "Accepting" do - before do - budget.update(phase: "accepting") - end - - context "Permissions" do - scenario "Verified user" do - login_as(level_two_user) - - visit budget_path(budget) - expect(page).to have_link "Create a budget investment" - end - - scenario "Unverified user" do - user = create(:user) - login_as(user) - - visit budget_path(budget) - - expect(page).to have_content "To create a new budget investment verify your account." - end - - scenario "user not logged in" do - visit budget_path(budget) - - expect(page).to have_content "To create a new budget investment you must sign in or sign up" - end - end - end end From 4adb7236dc66e0259fbcefbed987df8958ac9b7e Mon Sep 17 00:00:00 2001 From: decabeza Date: Thu, 6 May 2021 12:18:16 +0200 Subject: [PATCH 3/5] Add title to budget header --- app/assets/stylesheets/participation.scss | 14 ++++++++++++++ app/components/budgets/budget_component.html.erb | 1 + spec/components/budgets/budget_component_spec.rb | 1 + 3 files changed, 16 insertions(+) diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss index 4e0ea542e..371f44f58 100644 --- a/app/assets/stylesheets/participation.scss +++ b/app/assets/stylesheets/participation.scss @@ -1135,6 +1135,20 @@ padding-bottom: $line-height; padding-top: $line-height; + .budget-title { + font-weight: bold; + text-transform: uppercase; + + &::after { + border-bottom: 2px solid #fff; + content: ""; + margin: 0 auto; + padding-top: $line-height / 2; + display: block; + width: 20%; + } + } + h1, h2, p, diff --git a/app/components/budgets/budget_component.html.erb b/app/components/budgets/budget_component.html.erb index 30053714c..5e8038917 100644 --- a/app/components/budgets/budget_component.html.erb +++ b/app/components/budgets/budget_component.html.erb @@ -1,6 +1,7 @@
+ <%= t("budgets.index.title") %>

<%= budget.name %>

<%= auto_link_already_sanitized_html wysiwyg(budget.description) %> diff --git a/spec/components/budgets/budget_component_spec.rb b/spec/components/budgets/budget_component_spec.rb index f25820bb1..96469e22f 100644 --- a/spec/components/budgets/budget_component_spec.rb +++ b/spec/components/budgets/budget_component_spec.rb @@ -16,6 +16,7 @@ describe Budgets::BudgetComponent, type: :component do render_inline Budgets::BudgetComponent.new(budget) within(".budget-header") do + expect(page).to have_content("PARTICIPATORY BUDGETS") expect(page).to have_content(budget.name) expect(page).to have_content(budget.description) expect(page).to have_link("Help with participatory budgets") From 090f1bcddb2b9f29e24920c327cec8e73feeeb6c Mon Sep 17 00:00:00 2001 From: decabeza Date: Thu, 6 May 2021 12:19:30 +0200 Subject: [PATCH 4/5] Not showing the phase description in the budget header This description of the current phase is already being displayed on the same page in the section "Participatory budgets phases" --- app/components/budgets/budget_component.html.erb | 3 --- spec/components/budgets/budget_component_spec.rb | 1 - 2 files changed, 4 deletions(-) diff --git a/app/components/budgets/budget_component.html.erb b/app/components/budgets/budget_component.html.erb index 5e8038917..635344fee 100644 --- a/app/components/budgets/budget_component.html.erb +++ b/app/components/budgets/budget_component.html.erb @@ -3,9 +3,6 @@
<%= t("budgets.index.title") %>

<%= budget.name %>

-
- <%= auto_link_already_sanitized_html wysiwyg(budget.description) %> -

<%= link_to t("budgets.index.section_header.help"), "#section_help" %> diff --git a/spec/components/budgets/budget_component_spec.rb b/spec/components/budgets/budget_component_spec.rb index 96469e22f..799e03e12 100644 --- a/spec/components/budgets/budget_component_spec.rb +++ b/spec/components/budgets/budget_component_spec.rb @@ -18,7 +18,6 @@ describe Budgets::BudgetComponent, type: :component do within(".budget-header") do expect(page).to have_content("PARTICIPATORY BUDGETS") expect(page).to have_content(budget.name) - expect(page).to have_content(budget.description) expect(page).to have_link("Help with participatory budgets") end end From d78f2e03ad304138dcf5a7c813bd915142106e5f Mon Sep 17 00:00:00 2001 From: decabeza Date: Thu, 6 May 2021 12:20:50 +0200 Subject: [PATCH 5/5] Render link to budget header MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Allow to define a link (text and url) on budget form for render on the budget header. - Improve styles Co-authored-by: Senén Rodero Rodríguez --- app/assets/stylesheets/admin.scss | 5 +++ app/assets/stylesheets/participation.scss | 17 +++++++++- .../admin/budgets/form_component.html.erb | 33 ++++++++++++++----- .../budgets/budget_component.html.erb | 6 +++- app/controllers/admin/budgets_controller.rb | 1 + app/models/budget.rb | 3 +- config/locales/en/activerecord.yml | 2 ++ config/locales/en/admin.yml | 3 ++ config/locales/es/activerecord.yml | 2 ++ config/locales/es/admin.yml | 3 ++ ...20200213163214_add_main_link_to_budgets.rb | 6 ++++ db/schema.rb | 2 ++ .../budgets/budget_component_spec.rb | 16 +++++++++ spec/models/budget_spec.rb | 23 +++++++++++++ spec/models/concerns/globalizable.rb | 3 ++ spec/system/admin/budgets_spec.rb | 15 +++++++++ spec/system/admin/translatable_spec.rb | 2 +- 17 files changed, 130 insertions(+), 12 deletions(-) create mode 100644 db/migrate/20200213163214_add_main_link_to_budgets.rb diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 17e221cf7..fbb7a3176 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -293,6 +293,11 @@ $table-header: #ecf1f6; } } + .form-label { + font-weight: bold; + margin-bottom: 0; + } + .menu.simple { margin-bottom: $line-height / 2; diff --git a/app/assets/stylesheets/participation.scss b/app/assets/stylesheets/participation.scss index 371f44f58..947d347ff 100644 --- a/app/assets/stylesheets/participation.scss +++ b/app/assets/stylesheets/participation.scss @@ -1132,8 +1132,9 @@ .budget-header { @extend %brand-background; margin-top: -$line-height; + min-height: $line-height * 25; padding-bottom: $line-height; - padding-top: $line-height; + padding-top: $line-height * 4; .budget-title { font-weight: bold; @@ -1149,6 +1150,11 @@ } } + h1 { + font-size: rem-calc(60); + padding: $line-height * 2 0 $line-height; + } + h1, h2, p, @@ -1176,6 +1182,15 @@ text-transform: uppercase; } } + + .main-link { + @include regular-button($color: rgba(0, 0, 0, 0.5)); + + font-size: 1.25rem; + margin-bottom: $line-height * 2; + min-width: 30%; + text-decoration: none; + } } .jumbo-budget { diff --git a/app/components/admin/budgets/form_component.html.erb b/app/components/admin/budgets/form_component.html.erb index 57a3f8d44..621804c8f 100644 --- a/app/components/admin/budgets/form_component.html.erb +++ b/app/components/admin/budgets/form_component.html.erb @@ -5,19 +5,36 @@ <%= render "shared/errors", resource: budget %> <%= f.translatable_fields do |translations_form| %> -

- <%= translations_form.text_field :name, - maxlength: Budget.title_max_length, - hint: t("admin.budgets.edit.name_description") %> +
+
+ <%= translations_form.text_field :name, + maxlength: Budget.title_max_length, + hint: t("admin.budgets.edit.name_description") %> +
+
+
+
+

<%= t("admin.budgets.edit.main_call_to_action") %>

+

<%= t("admin.budgets.edit.main_call_to_action_description") %>

+ <%= translations_form.text_field :main_link_text %> +
<% end %> -
- <%= f.select :voting_style, voting_styles_select_options %> +
+
+ <%= f.text_field :main_link_url, placeholder: t("admin.shared.example_url") %> +
-
- <%= f.select :currency_symbol, currency_symbol_select_options %> +
+
+ <%= f.select :voting_style, voting_styles_select_options %> +
+ +
+ <%= f.select :currency_symbol, currency_symbol_select_options %> +
diff --git a/app/components/budgets/budget_component.html.erb b/app/components/budgets/budget_component.html.erb index 635344fee..c4f3c40f2 100644 --- a/app/components/budgets/budget_component.html.erb +++ b/app/components/budgets/budget_component.html.erb @@ -1,9 +1,13 @@
-
+
<%= t("budgets.index.title") %>

<%= budget.name %>

+ <% if budget.main_link_text.present? && budget.main_link_url.present? %> + <%= link_to budget.main_link_text, budget.main_link_url, class: "main-link" %> + <% end %> +

<%= link_to t("budgets.index.section_header.help"), "#section_help" %>

diff --git a/app/controllers/admin/budgets_controller.rb b/app/controllers/admin/budgets_controller.rb index 572d55fc1..030a86916 100644 --- a/app/controllers/admin/budgets_controller.rb +++ b/app/controllers/admin/budgets_controller.rb @@ -61,6 +61,7 @@ class Admin::BudgetsController < Admin::BaseController valid_attributes = [:phase, :currency_symbol, :voting_style, + :main_link_url, administrator_ids: [], valuator_ids: [] ] + descriptions diff --git a/app/models/budget.rb b/app/models/budget.rb index dba0d6e0b..c7152676d 100644 --- a/app/models/budget.rb +++ b/app/models/budget.rb @@ -4,7 +4,7 @@ class Budget < ApplicationRecord include StatsVersionable include Reportable - translates :name, touch: true + translates :name, :main_link_text, touch: true include Globalizable class Translation @@ -27,6 +27,7 @@ class Budget < ApplicationRecord validates :currency_symbol, presence: true validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/ validates :voting_style, inclusion: { in: VOTING_STYLES } + validates :main_link_url, presence: true, if: -> { main_link_text.present? } has_many :investments, dependent: :destroy has_many :ballots, dependent: :destroy diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml index e76c00725..cb49d44dd 100644 --- a/config/locales/en/activerecord.yml +++ b/config/locales/en/activerecord.yml @@ -160,7 +160,9 @@ en: voting_style: "Final voting style" voting_style_knapsack: "Knapsack" voting_style_approval: "Approval" + main_link_url: "The link takes you to (add a link)" budget/translation: + main_link_text: "Text on the link" name: "Name" budget/investment: heading_id: "Heading" diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index 144cb6503..1712cb291 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -121,6 +121,8 @@ en: empty_administrators: "There are no administrators" empty_valuators: "There are no valuators" name_description: "This is the name of the participatory budget used on the header and cards whenever it is active" + main_call_to_action: "Main call to action (optional)" + main_call_to_action_description: "This link will appear on main banner of this participatory budget and encourages your user to perform a specific action like creating a proposal, voting for existing ones, or learn more about the process." info: budget_settings: "General participatory budget settings" phases_settings: "Phases settings" @@ -1350,6 +1352,7 @@ en: color_help: Hexadecimal format show_results_and_stats: "Show results and stats" results_and_stats_reminder: "Marking these checkboxes the results and/or stats will be publicly available and every user will see them." + example_url: "https://consulproject.org" geozones: index: title: Geozone diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml index 5811a7afe..775cff009 100644 --- a/config/locales/es/activerecord.yml +++ b/config/locales/es/activerecord.yml @@ -160,7 +160,9 @@ es: voting_style: "Estilo de la votación final" voting_style_knapsack: Bolsa de dinero voting_style_approval: Por aprobación + main_link_url: "El enlace te lleva a (añade un enlace)" budget/translation: + main_link_text: "Texto del enlace" name: "Nombre" budget/investment: heading_id: "Partida presupuestaria" diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index e45e5bb13..8394f896b 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -121,6 +121,8 @@ es: empty_administrators: "No hay administradores" empty_valuators: "No hay evaluadores" name_description: "Este es el nombre del presupuesto participativo usado en la cabecera y tarjetas cuando éste está activo" + main_call_to_action: "Enlace de acción principal (opcional)" + main_call_to_action_description: "Este enlace aparecerá en la cabecera de este presupuesto participativo y permite al usuario ejecutar una acción específica como crear una nueva propuesta, votar las existentes, o leer más sobre el funcionamiento de los presupuestos participativos." info: budget_settings: "Configuración genérica del presupuesto participativo" phases_settings: "Configuración de las fases" @@ -1349,6 +1351,7 @@ es: color_help: Formato hexadecimal show_results_and_stats: "Mostrar resultados y estadísticas" results_and_stats_reminder: "Si marcas estas casillas los resultados y/o estadísticas serán públicos y podrán verlos todos los usuarios." + example_url: "https://consulproject.org" geozones: index: title: Zonas diff --git a/db/migrate/20200213163214_add_main_link_to_budgets.rb b/db/migrate/20200213163214_add_main_link_to_budgets.rb new file mode 100644 index 000000000..35207c730 --- /dev/null +++ b/db/migrate/20200213163214_add_main_link_to_budgets.rb @@ -0,0 +1,6 @@ +class AddMainLinkToBudgets < ActiveRecord::Migration[5.2] + def change + add_column :budgets, :main_link_url, :string + add_column :budget_translations, :main_link_text, :string + end +end diff --git a/db/schema.rb b/db/schema.rb index 5d116c21b..d13bbd02f 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -318,6 +318,7 @@ ActiveRecord::Schema.define(version: 2021_01_23_100638) do t.datetime "created_at", null: false t.datetime "updated_at", null: false t.string "name" + t.string "main_link_text" t.index ["budget_id"], name: "index_budget_translations_on_budget_id" t.index ["locale"], name: "index_budget_translations_on_locale" end @@ -362,6 +363,7 @@ ActiveRecord::Schema.define(version: 2021_01_23_100638) do t.text "description_informing" t.string "voting_style", default: "knapsack" t.boolean "published" + t.string "main_link_url" end create_table "campaigns", id: :serial, force: :cascade do |t| diff --git a/spec/components/budgets/budget_component_spec.rb b/spec/components/budgets/budget_component_spec.rb index 799e03e12..6aafa1409 100644 --- a/spec/components/budgets/budget_component_spec.rb +++ b/spec/components/budgets/budget_component_spec.rb @@ -21,6 +21,22 @@ describe Budgets::BudgetComponent, type: :component do expect(page).to have_link("Help with participatory budgets") end end + + it "shows budget main link when defined" do + render_inline Budgets::BudgetComponent.new(budget) + + within(".budget-header") do + expect(page).not_to have_css("a.main-link") + end + + budget.update!(main_link_text: "Partitipate now!", main_link_url: "https://consulproject.org") + + render_inline Budgets::BudgetComponent.new(budget) + + within(".budget-header") do + expect(page).to have_css("a.main-link", text: "Participate now!", href: "https://consulproject.org") + end + end end describe "map" do diff --git a/spec/models/budget_spec.rb b/spec/models/budget_spec.rb index e82485cb7..bbe5835f1 100644 --- a/spec/models/budget_spec.rb +++ b/spec/models/budget_spec.rb @@ -114,6 +114,29 @@ describe Budget do end end + describe "main_link_url" do + it "is not required if main_link_text is not provided" do + valid_budget = build(:budget, main_link_text: nil) + + expect(valid_budget).to be_valid + end + + it "is required if main_link_text is provided" do + invalid_budget = build(:budget, main_link_text: "link text") + + expect(invalid_budget).not_to be_valid + expect(invalid_budget.errors.count).to be 1 + expect(invalid_budget.errors[:main_link_url].count).to be 1 + expect(invalid_budget.errors[:main_link_url].first).to eq "can't be blank" + end + + it "is valid if main_link_text and main_link_url are both provided" do + valid_budget = build(:budget, main_link_text: "Text link", main_link_url: "https://consulproject.org") + + expect(valid_budget).to be_valid + end + end + describe "phase" do it "is validated" do Budget::Phase::PHASE_KINDS.each do |phase| diff --git a/spec/models/concerns/globalizable.rb b/spec/models/concerns/globalizable.rb index dce50d4af..21f4bd556 100644 --- a/spec/models/concerns/globalizable.rb +++ b/spec/models/concerns/globalizable.rb @@ -13,6 +13,9 @@ shared_examples_for "globalizable" do |factory_name| let(:attribute) { required_fields.sample || fields.sample } before do + if factory_name == :budget + record.main_link_url = "https://consulproject.org" + end record.update!(attribute => "In English") I18n.with_locale(:es) do diff --git a/spec/system/admin/budgets_spec.rb b/spec/system/admin/budgets_spec.rb index 1f5a755d8..fd3b65a13 100644 --- a/spec/system/admin/budgets_spec.rb +++ b/spec/system/admin/budgets_spec.rb @@ -233,6 +233,21 @@ describe "Admin budgets", :admin do end end + scenario "Show CTA link in public site if added" do + visit edit_admin_budget_path(budget) + + expect(page).to have_content("Main call to action (optional)") + + fill_in "Text on the link", with: "Participate now" + fill_in "The link takes you to (add a link)", with: "https://consulproject.org" + click_button "Update Budget" + + expect(page).to have_content "Participatory budget updated successfully" + + visit budgets_path + expect(page).to have_link("Participate now", href: "https://consulproject.org") + end + scenario "Changing name for current locale will update the slug if budget is in draft phase" do budget.update!(published: false, name: "Old English Name") diff --git a/spec/system/admin/translatable_spec.rb b/spec/system/admin/translatable_spec.rb index 491efcf5d..4cf6868a8 100644 --- a/spec/system/admin/translatable_spec.rb +++ b/spec/system/admin/translatable_spec.rb @@ -122,7 +122,7 @@ describe "Admin edit translatable records", :admin do let(:translatable) { create(:budget_investment) } context "Input field" do - let(:translatable) { create(:budget) } + let(:translatable) { create(:budget, main_link_url: "https://consulproject.org") } scenario "Shows validation erros" do visit edit_admin_budget_path(translatable)