Added feature to add content block to headings in sidebar -- rebase

This commit is contained in:
Milber Champutiz Burbano
2018-11-27 09:37:35 -05:00
parent e23fbc8d58
commit 9f455b9165
25 changed files with 289 additions and 48 deletions

View File

@@ -33,7 +33,7 @@ class Admin::BudgetHeadingsController < Admin::BaseController
private private
def budget_heading_params def budget_heading_params
params.require(:budget_heading).permit(:name, :price, :population) params.require(:budget_heading).permit(:name, :price, :population, :allow_custom_content)
end end
end end

View File

@@ -1,12 +1,23 @@
class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomization::BaseController class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomization::BaseController
load_and_authorize_resource :content_block, class: "SiteCustomization::ContentBlock" load_and_authorize_resource :content_block, class: "SiteCustomization::ContentBlock",
except: [:delete_heading_content_block, :edit_heading_content_block, :update_heading_content_block]
def index def index
@content_blocks = SiteCustomization::ContentBlock.order(:name, :locale) @content_blocks = SiteCustomization::ContentBlock.order(:name, :locale)
@headings_content_blocks = Budget::ContentBlock.all
end end
def create def create
if @content_block.save if is_heading_content_block?(@content_block.name)
heading_content_block = new_heading_content_block
if heading_content_block.save
notice = t('admin.site_customization.content_blocks.create.notice')
redirect_to admin_site_customization_content_blocks_path, notice: notice
else
flash.now[:error] = t('admin.site_customization.content_blocks.create.error')
render :new
end
elsif @content_block.save
notice = t('admin.site_customization.content_blocks.create.notice') notice = t('admin.site_customization.content_blocks.create.notice')
redirect_to admin_site_customization_content_blocks_path, notice: notice redirect_to admin_site_customization_content_blocks_path, notice: notice
else else
@@ -15,8 +26,22 @@ class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomizati
end end
end end
def edit
@selected_content_block = (@content_block.is_a? SiteCustomization::ContentBlock) ? @content_block.name : "hcb_#{ @content_block.heading_id }"
end
def update def update
if @content_block.update(content_block_params) if is_heading_content_block?(params[:site_customization_content_block][:name])
heading_content_block = new_heading_content_block
if heading_content_block.save
@content_block.destroy
notice = t('admin.site_customization.content_blocks.create.notice')
redirect_to admin_site_customization_content_blocks_path, notice: notice
else
flash.now[:error] = t('admin.site_customization.content_blocks.create.error')
render :new
end
elsif @content_block.update(content_block_params)
notice = t('admin.site_customization.content_blocks.update.notice') notice = t('admin.site_customization.content_blocks.update.notice')
redirect_to admin_site_customization_content_blocks_path, notice: notice redirect_to admin_site_customization_content_blocks_path, notice: notice
else else
@@ -31,6 +56,48 @@ class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomizati
redirect_to admin_site_customization_content_blocks_path, notice: notice redirect_to admin_site_customization_content_blocks_path, notice: notice
end end
def delete_heading_content_block
heading_content_block = Budget::ContentBlock.find(params[:id])
heading_content_block.destroy if heading_content_block
notice = t('admin.site_customization.content_blocks.destroy.notice')
redirect_to admin_site_customization_content_blocks_path, notice: notice
end
def edit_heading_content_block
@content_block = Budget::ContentBlock.find(params[:id])
@selected_content_block = (@content_block.is_a? Budget::ContentBlock) ? "hcb_#{ @content_block.heading_id }" : @content_block.heading.name
@is_heading_content_block = true
render :edit
end
def update_heading_content_block
heading_content_block = Budget::ContentBlock.find(params[:id])
if is_heading_content_block?(params[:name])
heading_content_block.locale = params[:locale]
heading_content_block.body = params[:body]
if heading_content_block.save
notice = t('admin.site_customization.content_blocks.update.notice')
redirect_to admin_site_customization_content_blocks_path, notice: notice
else
flash.now[:error] = t('admin.site_customization.content_blocks.update.error')
render :edit
end
else
@content_block = SiteCustomization::ContentBlock.new
@content_block.name = params[:name]
@content_block.locale = params[:locale]
@content_block.body = params[:body]
if @content_block.save
heading_content_block.destroy
notice = t('admin.site_customization.content_blocks.update.notice')
redirect_to admin_site_customization_content_blocks_path, notice: notice
else
flash.now[:error] = t('admin.site_customization.content_blocks.update.error')
render :edit
end
end
end
private private
def content_block_params def content_block_params
@@ -40,4 +107,16 @@ class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomizati
:body :body
) )
end end
def is_heading_content_block?(name)
name.start_with?('hcb_')
end
def new_heading_content_block
heading_content_block = Budget::ContentBlock.new
heading_content_block.body = params[:site_customization_content_block][:body]
heading_content_block.locale = params[:site_customization_content_block][:locale]
heading_content_block.heading_id = params[:site_customization_content_block][:name].sub('hcb_', '').to_i
heading_content_block
end
end end

View File

@@ -17,6 +17,7 @@ module Budgets
before_action :load_categories, only: [:index, :new, :create] before_action :load_categories, only: [:index, :new, :create]
before_action :set_default_budget_filter, only: :index before_action :set_default_budget_filter, only: :index
before_action :set_view, only: :index before_action :set_view, only: :index
before_action :load_content_blocks, only: :index
skip_authorization_check only: :json_data skip_authorization_check only: :json_data
@@ -149,6 +150,10 @@ module Budgets
@categories = ActsAsTaggableOn::Tag.category.order(:name) @categories = ActsAsTaggableOn::Tag.category.order(:name)
end end
def load_content_blocks
@heading_content_blocks = @heading.content_blocks.where(locale: I18n.locale) if @heading
end
def tag_cloud def tag_cloud
TagCloud.new(Budget::Investment, params[:search]) TagCloud.new(Budget::Investment, params[:search])
end end

View File

@@ -0,0 +1,9 @@
module ContentBlocksHelper
def valid_blocks
options = SiteCustomization::ContentBlock::VALID_BLOCKS.map { |key| [t("admin.site_customization.content_blocks.content_block.names.#{key}"), key] }
Budget::Heading.allow_custom_content.each do |heading|
options.push([heading.name, "hcb_#{heading.id}"])
end
options
end
end

View File

@@ -0,0 +1,9 @@
class Budget
class ContentBlock < ActiveRecord::Base
validates :locale, presence: true, inclusion: { in: I18n.available_locales.map(&:to_s) }
validates :heading, presence: true
validates_uniqueness_of :heading, scope: :locale
belongs_to :heading
end
end

View File

@@ -5,6 +5,7 @@ class Budget
belongs_to :group belongs_to :group
has_many :investments has_many :investments
has_many :content_blocks
validates :group_id, presence: true validates :group_id, presence: true
validates :name, presence: true, uniqueness: { if: :name_exists_in_budget_headings } validates :name, presence: true, uniqueness: { if: :name_exists_in_budget_headings }
@@ -15,6 +16,7 @@ class Budget
delegate :budget, :budget_id, to: :group, allow_nil: true delegate :budget, :budget_id, to: :group, allow_nil: true
scope :order_by_group_name, -> { includes(:group).order('budget_groups.name', 'budget_headings.name') } scope :order_by_group_name, -> { includes(:group).order('budget_groups.name', 'budget_headings.name') }
scope :allow_custom_content, -> { where(allow_custom_content: true).order(:name) }
def name_scoped_by_group def name_scoped_by_group
group.single_heading_group? ? name : "#{group.name}: #{name}" group.single_heading_group? ? name : "#{group.name}: #{name}"

View File

@@ -1,7 +1,7 @@
<table> <table>
<thead> <thead>
<tr> <tr>
<th colspan="4" class="with-button"> <th colspan="5" class="with-button">
<%= content_tag(:span, group.name, class:"group-toggle-#{group.id}", id:"group-name-#{group.id}") %> <%= content_tag(:span, group.name, class:"group-toggle-#{group.id}", id:"group-name-#{group.id}") %>
<%= content_tag(:span, (render 'admin/budgets/max_headings_label', current: group.max_votable_headings, max: group.headings.count, group: group if group.max_votable_headings), class:"small group-toggle-#{group.id}", id:"max-heading-label-#{group.id}") %> <%= content_tag(:span, (render 'admin/budgets/max_headings_label', current: group.max_votable_headings, max: group.headings.count, group: group if group.max_votable_headings), class:"small group-toggle-#{group.id}", id:"max-heading-label-#{group.id}") %>
@@ -17,6 +17,7 @@
<th><%= t("admin.budgets.form.table_heading") %></th> <th><%= t("admin.budgets.form.table_heading") %></th>
<th class="text-right"><%= t("admin.budgets.form.table_amount") %></th> <th class="text-right"><%= t("admin.budgets.form.table_amount") %></th>
<th class="text-right"><%= t("admin.budgets.form.table_population") %></th> <th class="text-right"><%= t("admin.budgets.form.table_population") %></th>
<th class="text-right"><%= t("admin.budgets.form.table_allow_custom_contents") %></th>
<th><%= t("admin.actions.actions") %></th> <th><%= t("admin.actions.actions") %></th>
</tr> </tr>
<% end %> <% end %>
@@ -26,7 +27,7 @@
<% if headings.blank? %> <% if headings.blank? %>
<tr> <tr>
<td colspan="4"> <td colspan="5">
<div class="callout primary"> <div class="callout primary">
<%= t("admin.budgets.form.no_heading") %> <%= t("admin.budgets.form.no_heading") %>
</div> </div>
@@ -35,7 +36,7 @@
<% end %> <% end %>
<tr id="group-<%= group.id %>-new-heading-form" style="display:none"> <tr id="group-<%= group.id %>-new-heading-form" style="display:none">
<td colspan="4"> <td colspan="5">
<%= render "admin/budgets/heading_form", group: group, budget: @budget, heading: Budget::Heading.new %> <%= render "admin/budgets/heading_form", group: group, budget: @budget, heading: Budget::Heading.new %>
</td> </td>
</tr> </tr>

View File

@@ -8,6 +8,9 @@
<td class="text-right"> <td class="text-right">
<%= heading.population %> <%= heading.population %>
</td> </td>
<td class="text-right">
<%= heading.allow_custom_content ? t("true_value") : t("false_value") %>
</td>
<td> <td>
<%= link_to t("admin.actions.edit"), <%= link_to t("admin.actions.edit"),
edit_admin_budget_budget_group_budget_heading_path(budget_id: group.budget.id, budget_group_id: group.id, id: heading.id), edit_admin_budget_budget_group_budget_heading_path(budget_id: group.budget.id, budget_group_id: group.id, id: heading.id),

View File

@@ -35,5 +35,11 @@
</div> </div>
</div> </div>
<div class="row">
<div class="small-12 medium-6 column">
<%= f.check_box :allow_custom_content, label: t('admin.budgets.form.allow_content_block') %>
</div>
</div>
<%= f.submit t("admin.budgets.form.save_heading"), class: "button success" %> <%= f.submit t("admin.budgets.form.save_heading"), class: "button success" %>
<% end %> <% end %>

View File

@@ -1,35 +1,5 @@
<%= form_for [:admin, @content_block], html: {class: "edit_page", data: {watch_changes: true}} do |f| %> <% if @is_heading_content_block %>
<%= render 'form_heading_content_block' %>
<% if @content_block.errors.any? %> <% else %>
<%= render 'form_content_block' %>
<div id="error_explanation" data-alert class="callout alert" data-closable>
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
<span aria-hidden="true">&times;</span>
</button>
<strong>
<%= @content_block.errors.count %>
<%= t("admin.site_customization.content_blocks.errors.form.error", count: @content_block.errors.count) %>
</strong>
</div>
<% end %>
<div class="small-12 medium-6 column">
<%= f.label :name %>
<%= f.select :name, SiteCustomization::ContentBlock::VALID_BLOCKS.map { |key| [t("admin.site_customization.content_blocks.content_block.names.#{key}"), key] }, label: false %>
</div>
<div class="small-12 medium-6 column">
<%= f.label :locale %>
<%= f.select :locale, I18n.available_locales, label: false %>
</div>
<div class="small-12 column">
<%= f.label :body %>
<%= f.text_area :body, label: false, rows: 10 %>
<div class="small-12 medium-6 large-3">
<%= f.submit class: "button success expanded" %>
</div>
</div>
<% end %> <% end %>

View File

@@ -0,0 +1,35 @@
<%= form_for [:admin, @content_block], html: {class: "edit_page", data: {watch_changes: true}} do |f| %>
<% if @content_block.errors.any? %>
<div id="error_explanation" data-alert class="callout alert" data-closable>
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
<span aria-hidden="true">&times;</span>
</button>
<strong>
<%= @content_block.errors.count %>
<%= t("admin.site_customization.content_blocks.errors.form.error", count: @content_block.errors.count) %>
</strong>
</div>
<% end %>
<div class="small-12 medium-6 column">
<%= f.label :name %>
<%= f.select :name, options_for_select(valid_blocks, @selected_content_block), label: false %>
</div>
<div class="small-12 medium-6 column">
<%= f.label :locale %>
<%= f.select :locale, I18n.available_locales, label: false %>
</div>
<div class="small-12 column">
<%= f.label :body %>
<%= f.text_area :body, label: false, rows: 10 %>
<div class="small-12 medium-6 large-3">
<%= f.submit class: "button success expanded" %>
</div>
</div>
<% end %>

View File

@@ -0,0 +1,29 @@
<%= form_tag(admin_site_customization_update_heading_content_block_path(@content_block.id), method: "put") do %>
<% if @content_block.errors.any? %>
<div id="error_explanation" data-alert class="callout alert" data-closable>
<button class="close-button" aria-label="<%= t("application.close") %>" type="button" data-close>
<span aria-hidden="true">&times;</span>
</button>
<strong>
<%= @content_block.errors.count %>
<%= t("admin.site_customization.content_blocks.errors.form.error", count: @content_block.errors.count) %>
</strong>
</div>
<% end %>
<div class="small-12 medium-6 column">
<%= label_tag :name %>
<%= select_tag :name, options_for_select(valid_blocks, @selected_content_block), label: false %>
</div>
<div class="small-12 medium-6 column">
<%= label_tag :locale %>
<%= select_tag :locale, options_for_select(I18n.available_locales, @content_block.locale.to_sym), label: false %>
</div>
<div class="small-12 column">
<%= label_tag :body %>
<%= text_area_tag :body, @content_block.body, rows: 10 %>
<div class="small-12 medium-6 large-3">
<%= button_tag t("admin.menu.site_customization.buttons.content_block.update"), class: "button success expanded" %>
</div>
</div>
<% end %>

View File

@@ -1,11 +1,11 @@
<% provide :title do %> <% provide :title do %>
<%= t("admin.header.title") %> - <%= t("admin.menu.site_customization.content_blocks") %> - <%= @content_block.name %> (<%= @content_block.locale %>) <%= t("admin.header.title") %> - <%= t("admin.menu.site_customization.content_blocks") %> - <%= @content_block.try(:name) || @content_block.heading.try(:name) %> (<%= @content_block.locale %>)
<% end %> <% end %>
<%= back_link_to admin_site_customization_content_blocks_path %> <%= back_link_to admin_site_customization_content_blocks_path %>
<%= link_to t("admin.site_customization.content_blocks.index.delete"), <%= link_to t("admin.site_customization.content_blocks.index.delete"),
admin_site_customization_content_block_path(@content_block), (@is_heading_content_block ? admin_site_customization_delete_heading_content_block_path(@content_block.id) : admin_site_customization_content_block_path(@content_block)),
method: :delete, method: :delete,
class: "delete float-right" %> class: "delete float-right" %>

View File

@@ -17,7 +17,7 @@
<p class="margin-top"><%= t("admin.site_customization.content_blocks.footer_html") %></p> <p class="margin-top"><%= t("admin.site_customization.content_blocks.footer_html") %></p>
<% if @content_blocks.any? %> <% if @content_blocks.any? || @headings_content_blocks.any? %>
<table class="cms-page-list"> <table class="cms-page-list">
<thead> <thead>
<tr> <tr>
@@ -38,10 +38,21 @@
</td> </td>
</tr> </tr>
<% end %> <% end %>
<% @headings_content_blocks.each do |content_block| %>
<tr id="<%= dom_id(content_block) %>">
<td><%= link_to "#{content_block.heading.name} (#{content_block.locale})", admin_site_customization_edit_heading_content_block_path(content_block) %></td>
<td><%= content_block.body.html_safe %></td>
<td>
<%= link_to t("admin.site_customization.content_blocks.index.delete"),
admin_site_customization_delete_heading_content_block_path(content_block.id),
method: :delete, class: "button hollow alert" %>
</td>
</tr>
<% end %>
</tbody> </tbody>
</table> </table>
<% else %> <% else %>
<div class="callout primary"> <div class="callout primary">
<%= t("admin.site_customization.content_blocks.no_blocks") %> <%= t("admin.site_customization.content_blocks.no_blocks") %>
</div> </div-->
<% end %> <% end %>

View File

@@ -0,0 +1,9 @@
<% if @heading.allow_custom_content %>
<br>
<ul id="content_block" class="no-bullet categories">
<% @heading_content_blocks.each do |content_block| %>
<%= raw content_block.body %>
<% end %>
</ul>
<% end %>

View File

@@ -21,9 +21,13 @@
</p> </p>
<% end %> <% end %>
<% if @heading && !@heading.content_blocks.where(locale: I18n.locale).empty? %>
<%= render 'budgets/investments/content_blocks' %>
<% end %>
<%= render "shared/tag_cloud", taggable: 'budget/investment' %> <%= render "shared/tag_cloud", taggable: 'budget/investment' %>
<%= render 'budgets/investments/categories' %> <%= render 'budgets/investments/categories' %>
<% if @heading && can?(:show, @ballot) %> <% if @heading && can?(:show, @ballot) %>
<div class="sidebar-divider"></div> <div class="sidebar-divider"></div>

View File

@@ -1,4 +1,6 @@
en: en:
true_value: 'Yes'
false_value: 'No'
admin: admin:
header: header:
title: Administration title: Administration
@@ -128,9 +130,11 @@ en:
table_heading: Heading table_heading: Heading
table_amount: Amount table_amount: Amount
table_population: Population table_population: Population
table_allow_custom_contents: Custom content allowed
population_info: "Budget Heading population field is used for Statistic purposes at the end of the Budget to show for each Heading that represents an area with population what percentage voted. The field is optional so you can leave it empty if it doesn't apply." population_info: "Budget Heading population field is used for Statistic purposes at the end of the Budget to show for each Heading that represents an area with population what percentage voted. The field is optional so you can leave it empty if it doesn't apply."
max_votable_headings: "Maximum number of headings in which a user can vote" max_votable_headings: "Maximum number of headings in which a user can vote"
current_of_max_headings: "%{current} of %{max}" current_of_max_headings: "%{current} of %{max}"
allow_content_block: Allow content block
winners: winners:
calculate: Calculate Winner Investments calculate: Calculate Winner Investments
calculated: Winners being calculated, it may take a minute. calculated: Winners being calculated, it may take a minute.
@@ -576,6 +580,8 @@ en:
welcome: "Welcome" welcome: "Welcome"
buttons: buttons:
save: "Save" save: "Save"
content_block:
update: "Update Block"
title_moderated_content: Moderated content title_moderated_content: Moderated content
title_budgets: Budgets title_budgets: Budgets
title_polls: Polls title_polls: Polls

View File

@@ -1,4 +1,6 @@
es: es:
true_value: 'Si'
false_value: 'No'
admin: admin:
header: header:
title: Administración title: Administración
@@ -131,6 +133,7 @@ es:
population_info: "El campo población de las partidas presupuestarias se usa con fines estadísticos únicamente, con el objetivo de mostrar el porcentaje de votos habidos en cada partida que represente un área con población. Es un campo opcional, así que puedes dejarlo en blanco si no aplica." population_info: "El campo población de las partidas presupuestarias se usa con fines estadísticos únicamente, con el objetivo de mostrar el porcentaje de votos habidos en cada partida que represente un área con población. Es un campo opcional, así que puedes dejarlo en blanco si no aplica."
max_votable_headings: "Máximo número de partidas en que un usuario puede votar" max_votable_headings: "Máximo número de partidas en que un usuario puede votar"
current_of_max_headings: "%{current} de %{max}" current_of_max_headings: "%{current} de %{max}"
allow_content_block: Permite bloque de contenidos
winners: winners:
calculate: Calcular proyectos ganadores calculate: Calcular proyectos ganadores
calculated: Calculando ganadores, puede tardar un minuto. calculated: Calculando ganadores, puede tardar un minuto.
@@ -575,6 +578,8 @@ es:
welcome: "Bienvenido/a" welcome: "Bienvenido/a"
buttons: buttons:
save: "Guardar cambios" save: "Guardar cambios"
content_block:
update: "Actualizar Bloque"
title_moderated_content: Contenido moderado title_moderated_content: Contenido moderado
title_budgets: Presupuestos title_budgets: Presupuestos
title_polls: Votaciones title_polls: Votaciones

View File

@@ -211,6 +211,9 @@ namespace :admin do
resources :pages, except: [:show] resources :pages, except: [:show]
resources :images, only: [:index, :update, :destroy] resources :images, only: [:index, :update, :destroy]
resources :content_blocks, except: [:show] resources :content_blocks, except: [:show]
delete '/heading_content_blocks/:id', to: 'content_blocks#delete_heading_content_block', as: 'delete_heading_content_block'
get '/edit_heading_content_blocks/:id', to: 'content_blocks#edit_heading_content_block', as: 'edit_heading_content_block'
put '/update_heading_content_blocks/:id', to: 'content_blocks#update_heading_content_block', as: 'update_heading_content_block'
resources :information_texts, only: [:index] do resources :information_texts, only: [:index] do
post :update, on: :collection post :update, on: :collection
end end

View File

@@ -0,0 +1,5 @@
class AddAllowCustomContentToHeadings < ActiveRecord::Migration
def change
add_column :budget_headings, :allow_custom_content, :boolean, default: false
end
end

View File

@@ -0,0 +1,10 @@
class CreateHeadingContentBlocks < ActiveRecord::Migration
def change
create_table :budget_content_blocks do |t|
t.integer :heading_id, index: true, foreign_key: true
t.text :body
t.string :locale
t.timestamps null: false
end
end
end

View File

@@ -11,7 +11,7 @@
# #
# It's strongly recommended that you check this file into your version control system. # It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20181016204729) do ActiveRecord::Schema.define(version: 20181108142513) do
# These are extensions that must be enabled in order to support this database # These are extensions that must be enabled in order to support this database
enable_extension "plpgsql" enable_extension "plpgsql"
@@ -141,6 +141,16 @@ ActiveRecord::Schema.define(version: 20181016204729) do
t.datetime "updated_at", null: false t.datetime "updated_at", null: false
end end
create_table "budget_content_blocks", force: :cascade do |t|
t.integer "heading_id"
t.text "body"
t.string "locale"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "budget_content_blocks", ["heading_id"], name: "index_budget_content_blocks_on_heading_id", using: :btree
create_table "budget_groups", force: :cascade do |t| create_table "budget_groups", force: :cascade do |t|
t.integer "budget_id" t.integer "budget_id"
t.string "name", limit: 50 t.string "name", limit: 50
@@ -152,10 +162,11 @@ ActiveRecord::Schema.define(version: 20181016204729) do
create_table "budget_headings", force: :cascade do |t| create_table "budget_headings", force: :cascade do |t|
t.integer "group_id" t.integer "group_id"
t.string "name", limit: 50 t.string "name", limit: 50
t.integer "price", limit: 8 t.integer "price", limit: 8
t.integer "population" t.integer "population"
t.string "slug" t.string "slug"
t.boolean "allow_custom_content", default: false
end end
add_index "budget_headings", ["group_id"], name: "index_budget_headings_on_group_id", using: :btree add_index "budget_headings", ["group_id"], name: "index_budget_headings_on_group_id", using: :btree

View File

@@ -209,4 +209,10 @@ FactoryBot.define do
factory :valuator_group, class: ValuatorGroup do factory :valuator_group, class: ValuatorGroup do
sequence(:name) { |n| "Valuator Group #{n}" } sequence(:name) { |n| "Valuator Group #{n}" }
end end
factory :heading_content_block, class: 'Budget::ContentBlock' do
association :heading, factory: :budget_heading
locale 'en'
body 'Some heading contents'
end
end end

View File

@@ -9,10 +9,13 @@ feature "Admin custom content blocks" do
scenario "Index" do scenario "Index" do
block = create(:site_customization_content_block) block = create(:site_customization_content_block)
heading_block = create(:heading_content_block)
visit admin_site_customization_content_blocks_path visit admin_site_customization_content_blocks_path
expect(page).to have_content(block.name) expect(page).to have_content(block.name)
expect(page).to have_content(block.body) expect(page).to have_content(block.body)
expect(page).to have_content(heading_block.heading.name)
expect(page).to have_content(heading_block.body)
end end
context "Create" do context "Create" do

View File

@@ -0,0 +1,20 @@
require 'rails_helper'
RSpec.describe Budget::ContentBlock do
let(:block) { build(:heading_content_block) }
it "is valid" do
expect(block).to be_valid
end
it "Heading is unique per locale" do
heading_content_block_en = create(:heading_content_block, locale: "en")
invalid_block = build(:heading_content_block, heading: heading_content_block_en.heading, locale: "en")
expect(invalid_block).to be_invalid
expect(invalid_block.errors.full_messages).to include("Heading has already been taken")
valid_block = build(:heading_content_block, heading: heading_content_block_en.heading, locale: "es")
expect(valid_block).to be_valid
end
end