Render link to budget header

- 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 <senenrodero@gmail.com>
This commit is contained in:
decabeza
2021-05-06 12:20:50 +02:00
committed by taitus
parent 090f1bcddb
commit d78f2e03ad
17 changed files with 130 additions and 12 deletions

View File

@@ -293,6 +293,11 @@ $table-header: #ecf1f6;
} }
} }
.form-label {
font-weight: bold;
margin-bottom: 0;
}
.menu.simple { .menu.simple {
margin-bottom: $line-height / 2; margin-bottom: $line-height / 2;

View File

@@ -1132,8 +1132,9 @@
.budget-header { .budget-header {
@extend %brand-background; @extend %brand-background;
margin-top: -$line-height; margin-top: -$line-height;
min-height: $line-height * 25;
padding-bottom: $line-height; padding-bottom: $line-height;
padding-top: $line-height; padding-top: $line-height * 4;
.budget-title { .budget-title {
font-weight: bold; font-weight: bold;
@@ -1149,6 +1150,11 @@
} }
} }
h1 {
font-size: rem-calc(60);
padding: $line-height * 2 0 $line-height;
}
h1, h1,
h2, h2,
p, p,
@@ -1176,6 +1182,15 @@
text-transform: uppercase; 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 { .jumbo-budget {

View File

@@ -5,19 +5,36 @@
<%= render "shared/errors", resource: budget %> <%= render "shared/errors", resource: budget %>
<%= f.translatable_fields do |translations_form| %> <%= f.translatable_fields do |translations_form| %>
<div class="small-12 medium-9 large-6 column end"> <div class="row expanded">
<%= translations_form.text_field :name, <div class="small-12 medium-9 large-6 column end">
maxlength: Budget.title_max_length, <%= translations_form.text_field :name,
hint: t("admin.budgets.edit.name_description") %> maxlength: Budget.title_max_length,
hint: t("admin.budgets.edit.name_description") %>
</div>
</div>
<div class="row expanded">
<div class="small-12 medium-9 large-6 column end">
<p class="form-label"><%= t("admin.budgets.edit.main_call_to_action") %></p>
<p class="help-text"> <%= t("admin.budgets.edit.main_call_to_action_description") %></p>
<%= translations_form.text_field :main_link_text %>
</div>
</div> </div>
<% end %> <% end %>
<div class="small-12 medium-4 column"> <div class="row expanded">
<%= f.select :voting_style, voting_styles_select_options %> <div class="small-12 medium-9 large-6 column end">
<%= f.text_field :main_link_url, placeholder: t("admin.shared.example_url") %>
</div>
</div> </div>
<div class="small-12 medium-2 column end"> <div class="row expanded">
<%= f.select :currency_symbol, currency_symbol_select_options %> <div class="small-12 medium-4 column">
<%= f.select :voting_style, voting_styles_select_options %>
</div>
<div class="small-12 medium-2 column end">
<%= f.select :currency_symbol, currency_symbol_select_options %>
</div>
</div> </div>
</fieldset> </fieldset>

View File

@@ -1,9 +1,13 @@
<div class="budget-header"> <div class="budget-header">
<div class="row"> <div class="row">
<div class="small-12 column"> <div class="small-12 column text-center">
<span class="budget-title"><%= t("budgets.index.title") %></span> <span class="budget-title"><%= t("budgets.index.title") %></span>
<h1><%= budget.name %></h1> <h1><%= budget.name %></h1>
<% 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 %>
<p> <p>
<%= link_to t("budgets.index.section_header.help"), "#section_help" %> <%= link_to t("budgets.index.section_header.help"), "#section_help" %>
</p> </p>

View File

@@ -61,6 +61,7 @@ class Admin::BudgetsController < Admin::BaseController
valid_attributes = [:phase, valid_attributes = [:phase,
:currency_symbol, :currency_symbol,
:voting_style, :voting_style,
:main_link_url,
administrator_ids: [], administrator_ids: [],
valuator_ids: [] valuator_ids: []
] + descriptions ] + descriptions

View File

@@ -4,7 +4,7 @@ class Budget < ApplicationRecord
include StatsVersionable include StatsVersionable
include Reportable include Reportable
translates :name, touch: true translates :name, :main_link_text, touch: true
include Globalizable include Globalizable
class Translation class Translation
@@ -27,6 +27,7 @@ class Budget < ApplicationRecord
validates :currency_symbol, presence: true validates :currency_symbol, presence: true
validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/ validates :slug, presence: true, format: /\A[a-z0-9\-_]+\z/
validates :voting_style, inclusion: { in: VOTING_STYLES } 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 :investments, dependent: :destroy
has_many :ballots, dependent: :destroy has_many :ballots, dependent: :destroy

View File

@@ -160,7 +160,9 @@ en:
voting_style: "Final voting style" voting_style: "Final voting style"
voting_style_knapsack: "Knapsack" voting_style_knapsack: "Knapsack"
voting_style_approval: "Approval" voting_style_approval: "Approval"
main_link_url: "The link takes you to (add a link)"
budget/translation: budget/translation:
main_link_text: "Text on the link"
name: "Name" name: "Name"
budget/investment: budget/investment:
heading_id: "Heading" heading_id: "Heading"

View File

@@ -121,6 +121,8 @@ en:
empty_administrators: "There are no administrators" empty_administrators: "There are no administrators"
empty_valuators: "There are no valuators" 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" 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: info:
budget_settings: "General participatory budget settings" budget_settings: "General participatory budget settings"
phases_settings: "Phases settings" phases_settings: "Phases settings"
@@ -1350,6 +1352,7 @@ en:
color_help: Hexadecimal format color_help: Hexadecimal format
show_results_and_stats: "Show results and stats" 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." 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: geozones:
index: index:
title: Geozone title: Geozone

View File

@@ -160,7 +160,9 @@ es:
voting_style: "Estilo de la votación final" voting_style: "Estilo de la votación final"
voting_style_knapsack: Bolsa de dinero voting_style_knapsack: Bolsa de dinero
voting_style_approval: Por aprobación voting_style_approval: Por aprobación
main_link_url: "El enlace te lleva a (añade un enlace)"
budget/translation: budget/translation:
main_link_text: "Texto del enlace"
name: "Nombre" name: "Nombre"
budget/investment: budget/investment:
heading_id: "Partida presupuestaria" heading_id: "Partida presupuestaria"

View File

@@ -121,6 +121,8 @@ es:
empty_administrators: "No hay administradores" empty_administrators: "No hay administradores"
empty_valuators: "No hay evaluadores" empty_valuators: "No hay evaluadores"
name_description: "Este es el nombre del presupuesto participativo usado en la cabecera y tarjetas cuando éste está activo" 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: info:
budget_settings: "Configuración genérica del presupuesto participativo" budget_settings: "Configuración genérica del presupuesto participativo"
phases_settings: "Configuración de las fases" phases_settings: "Configuración de las fases"
@@ -1349,6 +1351,7 @@ es:
color_help: Formato hexadecimal color_help: Formato hexadecimal
show_results_and_stats: "Mostrar resultados y estadísticas" 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." 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: geozones:
index: index:
title: Zonas title: Zonas

View File

@@ -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

View File

@@ -318,6 +318,7 @@ ActiveRecord::Schema.define(version: 2021_01_23_100638) do
t.datetime "created_at", null: false t.datetime "created_at", null: false
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
t.string "name" t.string "name"
t.string "main_link_text"
t.index ["budget_id"], name: "index_budget_translations_on_budget_id" t.index ["budget_id"], name: "index_budget_translations_on_budget_id"
t.index ["locale"], name: "index_budget_translations_on_locale" t.index ["locale"], name: "index_budget_translations_on_locale"
end end
@@ -362,6 +363,7 @@ ActiveRecord::Schema.define(version: 2021_01_23_100638) do
t.text "description_informing" t.text "description_informing"
t.string "voting_style", default: "knapsack" t.string "voting_style", default: "knapsack"
t.boolean "published" t.boolean "published"
t.string "main_link_url"
end end
create_table "campaigns", id: :serial, force: :cascade do |t| create_table "campaigns", id: :serial, force: :cascade do |t|

View File

@@ -21,6 +21,22 @@ describe Budgets::BudgetComponent, type: :component do
expect(page).to have_link("Help with participatory budgets") expect(page).to have_link("Help with participatory budgets")
end end
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 end
describe "map" do describe "map" do

View File

@@ -114,6 +114,29 @@ describe Budget do
end end
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 describe "phase" do
it "is validated" do it "is validated" do
Budget::Phase::PHASE_KINDS.each do |phase| Budget::Phase::PHASE_KINDS.each do |phase|

View File

@@ -13,6 +13,9 @@ shared_examples_for "globalizable" do |factory_name|
let(:attribute) { required_fields.sample || fields.sample } let(:attribute) { required_fields.sample || fields.sample }
before do before do
if factory_name == :budget
record.main_link_url = "https://consulproject.org"
end
record.update!(attribute => "In English") record.update!(attribute => "In English")
I18n.with_locale(:es) do I18n.with_locale(:es) do

View File

@@ -233,6 +233,21 @@ describe "Admin budgets", :admin do
end end
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 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") budget.update!(published: false, name: "Old English Name")

View File

@@ -122,7 +122,7 @@ describe "Admin edit translatable records", :admin do
let(:translatable) { create(:budget_investment) } let(:translatable) { create(:budget_investment) }
context "Input field" do context "Input field" do
let(:translatable) { create(:budget) } let(:translatable) { create(:budget, main_link_url: "https://consulproject.org") }
scenario "Shows validation erros" do scenario "Shows validation erros" do
visit edit_admin_budget_path(translatable) visit edit_admin_budget_path(translatable)