Custom content blocks for top_links and footer

This commit is contained in:
Amaia Castro
2017-03-24 17:12:33 +01:00
parent ae3690ab5f
commit c1de2dced4
24 changed files with 435 additions and 10 deletions

3
.gitignore vendored
View File

@@ -30,4 +30,5 @@
.DS_Store
.ruby-gemset
public/sitemap.xml
public/sitemap.xml
public/system/

View File

@@ -0,0 +1,40 @@
class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomization::BaseController
load_and_authorize_resource :content_block, class: "SiteCustomization::ContentBlock"
def index
@content_blocks = SiteCustomization::ContentBlock.order(:name, :locale)
end
def create
if @content_block.save
redirect_to admin_site_customization_content_blocks_path, notice: t('admin.site_customization.content_blocks.create.notice')
else
flash.now[:error] = t('admin.site_customization.content_blocks.create.error')
render :new
end
end
def update
if @content_block.update(content_block_params)
redirect_to admin_site_customization_content_blocks_path, notice: t('admin.site_customization.content_blocks.update.notice')
else
flash.now[:error] = t('admin.site_customization.content_blocks.update.error')
render :edit
end
end
def destroy
@content_block.destroy
redirect_to admin_site_customization_content_blocks_path, notice: t('admin.site_customization.content_blocks.destroy.notice')
end
private
def content_block_params
params.require(:site_customization_content_block).permit(
:name,
:locale,
:body
)
end
end

View File

@@ -51,4 +51,8 @@ module ApplicationHelper
def image_path_for(filename)
SiteCustomization::Image.image_path_for(filename) || filename
end
def content_block(name, locale)
SiteCustomization::ContentBlock.block_for(name, locale)
end
end

View File

@@ -54,6 +54,7 @@ module Abilities
can :manage, SiteCustomization::Page
can :manage, SiteCustomization::Image
can :manage, SiteCustomization::ContentBlock
end
end
end

View File

@@ -0,0 +1,11 @@
class SiteCustomization::ContentBlock < ActiveRecord::Base
VALID_BLOCKS = %w(top_links footer)
validates :locale, presence: true, inclusion: { in: I18n.available_locales.map(&:to_s) }
validates :name, presence: true, uniqueness: { scope: :locale }, inclusion: { in: VALID_BLOCKS }
def self.block_for(name, locale)
locale ||= I18n.default_locale
find_by(name: name, locale: locale).try(:body)
end
end

View File

@@ -134,5 +134,11 @@
<span class="icon-settings"></span><%= t("admin.menu.site_customization.images") %>
<% end %>
</li>
<li <%= "class=active" if controller_name == "content_blocks" %>>
<%= link_to admin_site_customization_content_blocks_path do %>
<span class="icon-settings"></span><%= t("admin.menu.site_customization.content_blocks") %>
<% end %>
</li>
</ul>
</nav>

View File

@@ -0,0 +1,34 @@
<%= 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, SiteCustomization::ContentBlock::VALID_BLOCKS, 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 %>
<%= f.submit class: "button success" %>
</div>
<% end %>

View File

@@ -0,0 +1,15 @@
<% provide :title do %>
Admin - <%= t("admin.menu.site_customization.content_blocks") %> - <%= @content_block.name %> (<%= @content_block.locale %>)
<% end %>
<%= link_to admin_site_customization_content_blocks_path, class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.site_customization.content_blocks.edit.back") %>
<% end %>
<%= button_to t("admin.site_customization.content_blocks.index.delete"), admin_site_customization_content_block_path(@content_block), method: :delete, class: "button hollow alert float-right margin-right" %>
<div class="row margin-top">
<h2><%= t("admin.site_customization.content_blocks.edit.title") %></h2>
<%= render 'form' %>
</div>

View File

@@ -0,0 +1,29 @@
<% provide :title do %>
Admin - <%= t("admin.menu.site_customization.content_blocks") %>
<% end %>
<%= link_to t("admin.site_customization.content_blocks.index.create"), new_admin_site_customization_content_block_path, class: "button float-right margin-right" %>
<h2 class="inline-block"><%= t("admin.site_customization.content_blocks.index.title") %></h2>
<table class="cms_page_list">
<thead>
<tr>
<th><%= t("admin.site_customization.content_blocks.content_block.name") %></th>
<th><%= t("admin.site_customization.content_blocks.content_block.body") %></th>
<th></th>
</tr>
</thead>
<tbody>
<% @content_blocks.each do |content_block| %>
<tr id="<%= dom_id(content_block) %>">
<td><%= link_to "#{content_block.name} (#{content_block.locale})", edit_admin_site_customization_content_block_path(content_block) %></td>
<td><%= content_block.body %></td>
<td>
<%= button_to t("admin.site_customization.content_blocks.index.delete"),
admin_site_customization_content_block_path(content_block),
method: :delete, class: "button hollow alert" %>
</td>
</tr>
<% end %>
</tbody>
</table>

View File

@@ -0,0 +1,14 @@
<% provide :title do %>
Admin - <%= t("admin.menu.site_customization.content_blocks") %> - <%= t("admin.site_customization.content_blocks.new.title") %>
<% end %>
<%= link_to admin_site_customization_content_blocks_path, class: "back" do %>
<span class="icon-angle-left"></span>
<%= t("admin.site_customization.content_blocks.new.back") %>
<% end %>
<div class="row margin-top">
<h2><%= t("admin.site_customization.content_blocks.new.title") %></h2>
<%= render 'form' %>
</div>

View File

@@ -1,5 +1,5 @@
<footer>
<div class="row">
<div class="row">
<div class="small-12 large-4 column">
<h1 class="logo">
<%= link_to t("layouts.header.open_gov", open: "#{t('layouts.header.open')}").html_safe %>
@@ -25,7 +25,7 @@
<div class="small-12 medium-4 column">
<h2>
<%= link_to t("layouts.footer.transparency_title"), t("layouts.footer.transparency_url") %>
<%= link_to t("layouts.footer.transparency_title"), setting['transparency_url'].presence || t("layouts.footer.transparency_url") %>
</h2>
<p><%= t("layouts.footer.transparency_text") %></p>
</div>
@@ -96,4 +96,6 @@
</div>
</div>
</div>
<%= raw content_block("footer", I18n.locale) %>
</footer>

View File

@@ -1,21 +1,25 @@
<ul class="no-bullet external-links">
<li>
<%= link_to t("layouts.header.external_link_transparency"),
t("layouts.header.external_link_transparency_url"),
setting['transparency_url'].presence || t("layouts.header.external_link_transparency_url"),
target: "_blank",
title: t('shared.target_blank_html') %>
</li>
<li>
<%= link_to t("layouts.header.external_link_opendata"),
t("layouts.header.external_link_opendata_url"),
setting['opendata_url'].presence || t("layouts.header.external_link_opendata_url"),
target: "_blank",
title: t('shared.target_blank_html') %>
</li>
<% if setting['blog_url'] %>
<li>
<%= link_to setting['blog_url'], title: t('shared.target_blank_html'), target: "_blank" do %>
<%= t("layouts.header.external_link_blog") %>
<% end %>
<%= link_to t("layouts.header.external_link_blog"),
setting['blog_url'],
target: "_blank",
title: t('shared.target_blank_html') %>
</li>
<% end %>
<%= raw content_block("top_links", I18n.locale) %>
</ul>

View File

@@ -46,6 +46,9 @@ en:
site_customization/image:
one: Custom image
other: Custom images
site_customization/content_block:
one: Custom content block
other: Custom content blocks
attributes:
budget:
name: "Name"
@@ -119,6 +122,13 @@ en:
updated_at: Updated at
more_info_flag: Show in more information page
print_content_flag: Print content button
site_customization/image:
name: Name
image: Image
site_customization/content_block:
name: Name
locale: locale
body: Body
errors:
models:
user:

View File

@@ -46,6 +46,9 @@ es:
site_customization/image:
one: Imagen
other: Imágenes
site_customization/content_block:
one: Bloque
other: Bloques
attributes:
budget:
name: "Nombre"
@@ -114,6 +117,13 @@ es:
updated_at: última actualización
more_info_flag: Mostrar en la página de más información
print_content_flag: Botón de imprimir contenido
site_customization/image:
name: Nombre
image: Imagen
site_customization/content_block:
name: Nombre
locale: Idioma
body: Contenido
errors:
models:
user:

View File

@@ -210,6 +210,7 @@ en:
site_customization:
pages: Custom Pages
images: Custom Images
content_blocks: Custom content blocks
moderators:
index:
title: Moderators
@@ -479,6 +480,31 @@ en:
sms_code_not_confirmed: Has not confirmed the sms code
title: Incomplete verifications
site_customization:
content_blocks:
create:
notice: Content block created successfully
error: Content block couldn't be created
update:
notice: Content block updated successfully
error: Content block couldn't be updated
destroy:
notice: Content block deleted successfully
edit:
title: Editing content block
back: Back
errors:
form:
error: Error
index:
create: Create new content block
delete: Delete
title: Content blocks
new:
back: Back
title: Create new content block
content_block:
body: Body
name: Name
images:
index:
title: Custom images
@@ -493,7 +519,7 @@ en:
pages:
create:
notice: Page created successfully
error: Process couldn't be created
error: Page couldn't be created
update:
notice: Page updated successfully
error: Page couldn't be updated

View File

@@ -210,6 +210,7 @@ es:
site_customization:
pages: Personalizar páginas
images: Personalizar imágenes
content_blocks: Personalizar bloques
moderators:
index:
title: Moderadores
@@ -479,6 +480,31 @@ es:
sms_code_not_confirmed: No ha introducido su código de seguridad
title: Verificaciones incompletas
site_customization:
content_blocks:
create:
notice: Bloque creado correctamente
error: No se ha podido crear el bloque
update:
notice: Bloque actualizado correctamente
error: No se ha podido actualizar el bloque
destroy:
notice: Bloque borrado correctamente
edit:
title: Editar bloque
back: Volver
errors:
form:
error: Error
index:
create: Crear nuevo bloque
delete: Borrar
title: Bloques
new:
back: Volver
title: Crear nuevo bloque
content_block:
body: Contenido
name: Nombre
images:
index:
title: Personalizar imágenes

View File

@@ -226,6 +226,7 @@ Rails.application.routes.draw do
namespace :site_customization do
resources :pages, except: [:show]
resources :images, only: [:index, :update, :destroy]
resources :content_blocks, except: [:show]
end
end

View File

@@ -0,0 +1,13 @@
class CreateSiteCustomizationContentBlocks < ActiveRecord::Migration
def change
create_table :site_customization_content_blocks do |t|
t.string :name
t.string :locale
t.text :body
t.timestamps null: false
end
add_index :site_customization_content_blocks, [:name, :locale], unique: true
end
end

View File

@@ -11,7 +11,7 @@
#
# It's strongly recommended that you check this file into your version control system.
ActiveRecord::Schema.define(version: 20170322145702) do
ActiveRecord::Schema.define(version: 20170324101716) do
# These are extensions that must be enabled in order to support this database
enable_extension "plpgsql"
@@ -439,6 +439,16 @@ ActiveRecord::Schema.define(version: 20170322145702) do
t.datetime "updated_at"
end
create_table "site_customization_content_blocks", force: :cascade do |t|
t.string "name"
t.string "locale"
t.text "body"
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
end
add_index "site_customization_content_blocks", ["name", "locale"], name: "index_site_customization_content_blocks_on_name_and_locale", unique: true, using: :btree
create_table "site_customization_images", force: :cascade do |t|
t.string "name", null: false
t.string "image_file_name"

View File

@@ -51,6 +51,8 @@ Setting["facebook_handle"] = nil
Setting["youtube_handle"] = nil
Setting["telegram_handle"] = nil
Setting["blog_url"] = nil
Setting["transparency_url"] = nil
Setting["opendata_url"] = "/opendata"
# Public-facing URL of the app.
Setting["url"] = "http://example.com"

View File

@@ -468,4 +468,10 @@ FactoryGirl.define do
more_info_flag true
end
end
factory :site_customization_content_block, class: 'SiteCustomization::ContentBlock' do
name "top_links"
locale "en"
body "Some top links content"
end
end

View File

@@ -0,0 +1,107 @@
require 'rails_helper'
feature "Admin custom content blocks" do
background do
admin = create(:administrator)
login_as(admin.user)
end
scenario "Index" do
block = create(:site_customization_content_block)
visit admin_site_customization_content_blocks_path
expect(page).to have_content(block.name)
expect(page).to have_content(block.body)
end
context "Create" do
scenario "Valid custom block" do
visit admin_root_path
within("#side_menu") do
click_link "Custom content blocks"
end
expect(page).to_not have_content "footer (es)"
click_link "Create new content block"
select "footer", from: "site_customization_content_block_name"
select "es", from: "site_customization_content_block_locale"
fill_in "site_customization_content_block_body", with: "Some custom content"
click_button "Create Custom content block"
expect(page).to have_content "footer (es)"
expect(page).to have_content "Some custom content"
end
scenario "Invalid custom block" do
block = create(:site_customization_content_block)
visit admin_root_path
within("#side_menu") do
click_link "Custom content blocks"
end
expect(page).to have_content "top_links (en)"
click_link "Create new content block"
select "top_links", from: "site_customization_content_block_name"
select "en", from: "site_customization_content_block_locale"
fill_in "site_customization_content_block_body", with: "Some custom content"
click_button "Create Custom content block"
expect(page).to have_content "Content block couldn't be created"
expect(page).to have_content "has already been taken"
end
end
context "Update" do
scenario "Valid custom block" do
block = create(:site_customization_content_block)
visit admin_root_path
within("#side_menu") do
click_link "Custom content blocks"
end
click_link "top_links (en)"
fill_in "site_customization_content_block_body", with: "Some other custom content"
click_button "Update Custom content block"
expect(page).to have_content "Content block updated successfully"
expect(page).to have_content "Some other custom content"
end
end
context "Delete" do
scenario "From index page" do
block = create(:site_customization_content_block)
visit admin_site_customization_content_blocks_path
expect(page).to have_content("#{block.name} (#{block.locale})")
expect(page).to have_content(block.body)
click_button "Delete"
expect(page).to_not have_content("#{block.name} (#{block.locale})")
expect(page).to_not have_content(block.body)
end
scenario "From edit page" do
block = create(:site_customization_content_block)
visit edit_admin_site_customization_content_block_path(block)
click_button "Delete"
expect(page).to_not have_content("#{block.name} (#{block.locale})")
expect(page).to_not have_content(block.body)
end
end
end

View File

@@ -0,0 +1,33 @@
require 'rails_helper'
feature "Custom content blocks" do
scenario "top links" do
create(:site_customization_content_block, name: "top_links", locale: "en", body: "content for top links")
create(:site_customization_content_block, name: "top_links", locale: "es", body: "contenido para top links")
visit "/?locale=en"
expect(page).to have_content("content for top links")
expect(page).to_not have_content("contenido para top links")
visit "/?locale=es"
expect(page).to have_content("contenido para top links")
expect(page).to_not have_content("content for top links")
end
scenario "footer" do
create(:site_customization_content_block, name: "footer", locale: "en", body: "content for footer")
create(:site_customization_content_block, name: "footer", locale: "es", body: "contenido para footer")
visit "/?locale=en"
expect(page).to have_content("content for footer")
expect(page).to_not have_content("contenido para footer")
visit "/?locale=es"
expect(page).to have_content("contenido para footer")
expect(page).to_not have_content("content for footer")
end
end

View File

@@ -0,0 +1,20 @@
require 'rails_helper'
RSpec.describe SiteCustomization::ContentBlock, type: :model do
let(:block) { build(:site_customization_content_block) }
it "should be valid" do
expect(block).to be_valid
end
it "name is unique per locale" do
create(:site_customization_content_block, name: "top_links", locale: "en")
invalid_block = build(:site_customization_content_block, name: "top_links", locale: "en")
expect(invalid_block).to be_invalid
expect(invalid_block.errors.full_messages).to include("Name has already been taken")
valid_block = build(:site_customization_content_block, name: "top_links", locale: "es")
expect(valid_block).to be_valid
end
end