diff --git a/app/assets/stylesheets/budgets/phases.scss b/app/assets/stylesheets/budgets/phases.scss
index 93b27f496..9fee6e5d3 100644
--- a/app/assets/stylesheets/budgets/phases.scss
+++ b/app/assets/stylesheets/budgets/phases.scss
@@ -191,5 +191,10 @@
text-align: center;
}
}
+
+ .main-link {
+ @include regular-button;
+ font-size: 1.1rem;
+ }
}
}
diff --git a/app/components/admin/budget_phases/form_component.html.erb b/app/components/admin/budget_phases/form_component.html.erb
index b0e8a3af1..e8e0822c0 100644
--- a/app/components/admin/budget_phases/form_component.html.erb
+++ b/app/components/admin/budget_phases/form_component.html.erb
@@ -41,8 +41,18 @@
class: "html-area",
hint: t("admin.budget_phases.edit.description_help_text") %>
+
+
+
<%= t("admin.budget_phases.edit.main_call_to_action") %>
+
<%= t("admin.budget_phases.edit.main_call_to_action_description") %>
+ <%= translations_form.text_field :main_link_text %>
+
<% end %>
+
+ <%= f.text_field :main_link_url, placeholder: t("admin.shared.example_url") %>
+
+
<% if feature?(:allow_images) %>
<%= render "images/nested_image", imageable: @phase, f: f %>
diff --git a/app/components/budgets/phases_component.html.erb b/app/components/budgets/phases_component.html.erb
index ee58ae171..6e4b66bf0 100644
--- a/app/components/budgets/phases_component.html.erb
+++ b/app/components/budgets/phases_component.html.erb
@@ -47,6 +47,10 @@
<%= phase.name %>
<%= start_date(phase) %> - <%= end_date(phase) %>
<%= auto_link_already_sanitized_html(wysiwyg(phase.description)) %>
+
+ <% if phase.main_link_text.present? && phase.main_link_url.present? %>
+ <%= link_to phase.main_link_text, phase.main_link_url, class: "main-link" %>
+ <% end %>
<% if phase.image.present? %>
diff --git a/app/controllers/concerns/admin/budget_phases_actions.rb b/app/controllers/concerns/admin/budget_phases_actions.rb
index 5d09ddee3..6d0434416 100644
--- a/app/controllers/concerns/admin/budget_phases_actions.rb
+++ b/app/controllers/concerns/admin/budget_phases_actions.rb
@@ -31,7 +31,8 @@ module Admin::BudgetPhasesActions
end
def budget_phase_params
- valid_attributes = [:starts_at, :ends_at, :enabled, image_attributes: image_attributes]
+ valid_attributes = [:starts_at, :ends_at, :enabled, :main_link_url,
+ image_attributes: image_attributes]
params.require(:budget_phase).permit(*valid_attributes, translation_params(Budget::Phase))
end
end
diff --git a/app/models/budget/phase.rb b/app/models/budget/phase.rb
index 291386715..b6d4c64c5 100644
--- a/app/models/budget/phase.rb
+++ b/app/models/budget/phase.rb
@@ -8,6 +8,7 @@ class Budget
translates :name, touch: true
translates :summary, touch: true
translates :description, touch: true
+ translates :main_link_text, touch: true
include Globalizable
include Sanitizable
include Imageable
@@ -20,6 +21,7 @@ class Budget
validates_translation :description, length: { maximum: DESCRIPTION_MAX_LENGTH }
validates :budget, presence: true
validates :kind, presence: true, uniqueness: { scope: :budget }, inclusion: { in: ->(*) { PHASE_KINDS }}
+ validates :main_link_url, presence: true, if: -> { main_link_text.present? }
validate :invalid_dates_range?
validate :prev_phase_dates_valid?
validate :next_phase_dates_valid?
diff --git a/config/locales/en/activerecord.yml b/config/locales/en/activerecord.yml
index cb49d44dd..5539f91b0 100644
--- a/config/locales/en/activerecord.yml
+++ b/config/locales/en/activerecord.yml
@@ -231,10 +231,12 @@ en:
enabled: "Phase enabled"
ends_at: "End date"
starts_at: "Start date"
+ main_link_url: "The link takes you to (add a link)"
budget/phase/translation:
name: "Name"
description: "Description"
summary: "Summary"
+ main_link_text: "Text on the link"
comment:
body: "Comment"
user: "User"
diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml
index 179f02192..b6d1329b3 100644
--- a/config/locales/en/admin.yml
+++ b/config/locales/en/admin.yml
@@ -201,6 +201,8 @@ en:
duration_description: "The period of time this phase will be active."
enabled_help_text: This phase will be public in the budget's phases timeline, as well as active for any other purpose
image_description: "If an image is uplodaded it will be displayed next to the description of this phase."
+ 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 when this phase is enabled and encourages your user to perform a specific action like creating a proposal, voting for existing ones, or learn more about the process."
name_help_text: "This is the title of the phase users will read on the header whenever this phase is active."
save_changes: Save changes
index:
@@ -1352,6 +1354,7 @@ en:
content: Content
created_at: Created at
color_help: Hexadecimal format
+ example_url: "https://consulproject.org"
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"
diff --git a/config/locales/es/activerecord.yml b/config/locales/es/activerecord.yml
index 775cff009..d37a8a155 100644
--- a/config/locales/es/activerecord.yml
+++ b/config/locales/es/activerecord.yml
@@ -231,10 +231,12 @@ es:
enabled: "Fase habilitada"
ends_at: "Fecha de fin"
starts_at: "Fecha de inicio"
+ main_link_url: "El enlace te lleva a (añade un enlace)"
budget/phase/translation:
name: "Nombre"
description: "Descripción"
summary: "Resumen"
+ main_link_text: "Texto del enlace"
comment:
body: "Comentario"
user: "Usuario"
diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml
index 6209bc245..a5d7fe170 100644
--- a/config/locales/es/admin.yml
+++ b/config/locales/es/admin.yml
@@ -200,6 +200,8 @@ es:
duration_description: "El período de tiempo que esta fase estará activa."
enabled_help_text: Esta fase será pública en el calendario de fases del presupuesto y estará activa para otros propósitos
image_description: "Si se proporciona una imagen se mostrará junto a la descripción de esta fase."
+ 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 cuando esta fase esté activa 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."
name_help_text: "Este es el título de la fase que los usuarios leerán en el encabezado cuando la fase esté activa."
save_changes: Guardar cambios
title: "Editar fase"
@@ -1351,6 +1353,7 @@ es:
content: Contenido
created_at: Fecha de creación
color_help: Formato hexadecimal
+ example_url: "https://consulproject.org"
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"
diff --git a/db/migrate/20200309112812_add_main_link_to_budget_phases.rb b/db/migrate/20200309112812_add_main_link_to_budget_phases.rb
new file mode 100644
index 000000000..6813111b4
--- /dev/null
+++ b/db/migrate/20200309112812_add_main_link_to_budget_phases.rb
@@ -0,0 +1,6 @@
+class AddMainLinkToBudgetPhases < ActiveRecord::Migration[5.0]
+ def change
+ add_column :budget_phase_translations, :main_link_text, :string
+ add_column :budget_phases, :main_link_url, :string
+ end
+end
diff --git a/db/schema.rb b/db/schema.rb
index d13bbd02f..b69a16a90 100644
--- a/db/schema.rb
+++ b/db/schema.rb
@@ -287,6 +287,7 @@ ActiveRecord::Schema.define(version: 2021_01_23_100638) do
t.text "description"
t.text "summary"
t.string "name"
+ t.string "main_link_text"
t.index ["budget_phase_id"], name: "index_budget_phase_translations_on_budget_phase_id"
t.index ["locale"], name: "index_budget_phase_translations_on_locale"
end
@@ -298,6 +299,7 @@ ActiveRecord::Schema.define(version: 2021_01_23_100638) do
t.datetime "starts_at"
t.datetime "ends_at"
t.boolean "enabled", default: true
+ t.string "main_link_url"
t.index ["ends_at"], name: "index_budget_phases_on_ends_at"
t.index ["kind"], name: "index_budget_phases_on_kind"
t.index ["next_phase_id"], name: "index_budget_phases_on_next_phase_id"
diff --git a/spec/components/budgets/phases_component_spec.rb b/spec/components/budgets/phases_component_spec.rb
new file mode 100644
index 000000000..c67e1eb24
--- /dev/null
+++ b/spec/components/budgets/phases_component_spec.rb
@@ -0,0 +1,17 @@
+require "rails_helper"
+
+describe Budgets::PhasesComponent, type: :component do
+ let(:budget) { create(:budget) }
+
+ it "shows budget current phase main link when defined" do
+ render_inline Budgets::PhasesComponent.new(budget)
+
+ expect(page).not_to have_css(".main-link")
+
+ budget.current_phase.update!(main_link_text: "Phase link!", main_link_url: "https://consulproject.org")
+ render_inline Budgets::PhasesComponent.new(budget)
+
+ expect(page).to have_css(".main-link")
+ expect(page).to have_link("Phase link!", href: "https://consulproject.org")
+ end
+end
diff --git a/spec/models/budget/phase_spec.rb b/spec/models/budget/phase_spec.rb
index c5eccfaa2..58d70ca44 100644
--- a/spec/models/budget/phase_spec.rb
+++ b/spec/models/budget/phase_spec.rb
@@ -111,6 +111,29 @@ describe Budget::Phase do
expect(informing_phase).to be_valid
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
+ budget = build(:budget, main_link_text: "link text", main_link_url: "https://consulproject.org")
+
+ expect(budget).to be_valid
+ end
+ end
end
describe "#save" do
diff --git a/spec/models/concerns/globalizable.rb b/spec/models/concerns/globalizable.rb
index 21f4bd556..9a55a0b42 100644
--- a/spec/models/concerns/globalizable.rb
+++ b/spec/models/concerns/globalizable.rb
@@ -13,7 +13,7 @@ shared_examples_for "globalizable" do |factory_name|
let(:attribute) { required_fields.sample || fields.sample }
before do
- if factory_name == :budget
+ if factory_name == :budget || factory_name == :budget_phase
record.main_link_url = "https://consulproject.org"
end
record.update!(attribute => "In English")
diff --git a/spec/system/admin/budget_phases_spec.rb b/spec/system/admin/budget_phases_spec.rb
index eda219810..5ecd061ca 100644
--- a/spec/system/admin/budget_phases_spec.rb
+++ b/spec/system/admin/budget_phases_spec.rb
@@ -55,5 +55,21 @@ describe "Admin budget phases" do
expect(page).to have_content "Changes saved"
end
+
+ scenario "shows CTA link in public site if added" do
+ visit edit_admin_budget_budget_phase_path(budget, budget.current_phase)
+
+ expect(page).to have_content "Main call to action (optional)"
+
+ fill_in "Text on the link", with: "Link on the phase"
+ fill_in "The link takes you to (add a link)", with: "https://consulproject.org"
+ click_button "Save changes"
+
+ expect(page).to have_content("Changes saved")
+
+ visit budgets_path
+
+ expect(page).to have_link("Link on the phase", href: "https://consulproject.org")
+ end
end
end
diff --git a/spec/system/admin/translatable_spec.rb b/spec/system/admin/translatable_spec.rb
index 4cf6868a8..ea4b18059 100644
--- a/spec/system/admin/translatable_spec.rb
+++ b/spec/system/admin/translatable_spec.rb
@@ -2,6 +2,7 @@ require "rails_helper"
describe "Admin edit translatable records", :admin do
before do
+ translatable.main_link_url = "https://consulproject.org" if translatable.is_a?(Budget::Phase)
translatable.update!(attributes)
end