diff --git a/.gitignore b/.gitignore index 35f5651a4..a6f2826c3 100644 --- a/.gitignore +++ b/.gitignore @@ -30,4 +30,5 @@ .DS_Store .ruby-gemset -public/sitemap.xml \ No newline at end of file +public/sitemap.xml +public/system/ diff --git a/app/controllers/admin/site_customization/content_blocks_controller.rb b/app/controllers/admin/site_customization/content_blocks_controller.rb new file mode 100644 index 000000000..2f0843ccc --- /dev/null +++ b/app/controllers/admin/site_customization/content_blocks_controller.rb @@ -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 diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index c449fa9f4..0c23c0d22 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -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 diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index c61530772..a99b98fea 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -54,6 +54,7 @@ module Abilities can :manage, SiteCustomization::Page can :manage, SiteCustomization::Image + can :manage, SiteCustomization::ContentBlock end end end diff --git a/app/models/site_customization/content_block.rb b/app/models/site_customization/content_block.rb new file mode 100644 index 000000000..c08beb52e --- /dev/null +++ b/app/models/site_customization/content_block.rb @@ -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 diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 6a48b493b..65d8bed79 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -134,5 +134,11 @@ <%= t("admin.menu.site_customization.images") %> <% end %> + +
  • > + <%= link_to admin_site_customization_content_blocks_path do %> + <%= t("admin.menu.site_customization.content_blocks") %> + <% end %> +
  • diff --git a/app/views/admin/site_customization/content_blocks/_form.html.erb b/app/views/admin/site_customization/content_blocks/_form.html.erb new file mode 100644 index 000000000..9ca4eb36a --- /dev/null +++ b/app/views/admin/site_customization/content_blocks/_form.html.erb @@ -0,0 +1,34 @@ +<%= form_for [:admin, @content_block], html: {class: "edit_page", data: {watch_changes: true}} do |f| %> + + <% if @content_block.errors.any? %> + +
    + + + + <%= @content_block.errors.count %> + <%= t("admin.site_customization.content_blocks.errors.form.error", count: @content_block.errors.count) %> + +
    + + <% end %> + + +
    + <%= f.label :name %> + <%= f.select :name, SiteCustomization::ContentBlock::VALID_BLOCKS, label: false %> +
    +
    + <%= f.label :locale %> + <%= f.select :locale, I18n.available_locales, label: false %> +
    + +
    + <%= f.label :body %> + <%= f.text_area :body, label: false, rows: 10 %> + <%= f.submit class: "button success" %> +
    + +<% end %> diff --git a/app/views/admin/site_customization/content_blocks/edit.html.erb b/app/views/admin/site_customization/content_blocks/edit.html.erb new file mode 100644 index 000000000..c96f9a810 --- /dev/null +++ b/app/views/admin/site_customization/content_blocks/edit.html.erb @@ -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 %> + + <%= 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" %> + +
    +

    <%= t("admin.site_customization.content_blocks.edit.title") %>

    + <%= render 'form' %> +
    diff --git a/app/views/admin/site_customization/content_blocks/index.html.erb b/app/views/admin/site_customization/content_blocks/index.html.erb new file mode 100644 index 000000000..653e3e731 --- /dev/null +++ b/app/views/admin/site_customization/content_blocks/index.html.erb @@ -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" %> +

    <%= t("admin.site_customization.content_blocks.index.title") %>

    + + + + + + + + + + + <% @content_blocks.each do |content_block| %> + + + + + + <% end %> + +
    <%= t("admin.site_customization.content_blocks.content_block.name") %><%= t("admin.site_customization.content_blocks.content_block.body") %>
    <%= link_to "#{content_block.name} (#{content_block.locale})", edit_admin_site_customization_content_block_path(content_block) %><%= content_block.body %> + <%= button_to t("admin.site_customization.content_blocks.index.delete"), + admin_site_customization_content_block_path(content_block), + method: :delete, class: "button hollow alert" %> +
    diff --git a/app/views/admin/site_customization/content_blocks/new.html.erb b/app/views/admin/site_customization/content_blocks/new.html.erb new file mode 100644 index 000000000..75ff5f389 --- /dev/null +++ b/app/views/admin/site_customization/content_blocks/new.html.erb @@ -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 %> + + <%= t("admin.site_customization.content_blocks.new.back") %> +<% end %> + +
    +

    <%= t("admin.site_customization.content_blocks.new.title") %>

    + <%= render 'form' %> +
    + diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb index 4b5e90523..1e5c3dfa5 100644 --- a/app/views/layouts/_footer.html.erb +++ b/app/views/layouts/_footer.html.erb @@ -1,5 +1,5 @@ diff --git a/app/views/shared/_top_links.html.erb b/app/views/shared/_top_links.html.erb index b97499232..8a71130d6 100644 --- a/app/views/shared/_top_links.html.erb +++ b/app/views/shared/_top_links.html.erb @@ -1,21 +1,25 @@ diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index bd18422ae..806ddc96f 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -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: diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index f3397ef19..43c40110e 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -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: diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 5f84f69d3..12911c410 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -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 diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index f4c834e34..feb72e24c 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -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 diff --git a/config/routes.rb b/config/routes.rb index 51d2a47da..2088c48da 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -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 diff --git a/db/migrate/20170324101716_create_site_customization_content_blocks.rb b/db/migrate/20170324101716_create_site_customization_content_blocks.rb new file mode 100644 index 000000000..d0e4c3822 --- /dev/null +++ b/db/migrate/20170324101716_create_site_customization_content_blocks.rb @@ -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 diff --git a/db/schema.rb b/db/schema.rb index 938fbb9ec..e92a4121c 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -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" diff --git a/db/seeds.rb b/db/seeds.rb index be7960dff..bbbf0eb01 100644 --- a/db/seeds.rb +++ b/db/seeds.rb @@ -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" diff --git a/spec/factories.rb b/spec/factories.rb index 20a1f463c..116b612d5 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -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 diff --git a/spec/features/admin/site_customization/content_blocks_spec.rb b/spec/features/admin/site_customization/content_blocks_spec.rb new file mode 100644 index 000000000..cc5dca34c --- /dev/null +++ b/spec/features/admin/site_customization/content_blocks_spec.rb @@ -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 diff --git a/spec/features/site_customization/content_blocks_spec.rb b/spec/features/site_customization/content_blocks_spec.rb new file mode 100644 index 000000000..995982063 --- /dev/null +++ b/spec/features/site_customization/content_blocks_spec.rb @@ -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 diff --git a/spec/models/site_customization/content_block_spec.rb b/spec/models/site_customization/content_block_spec.rb new file mode 100644 index 000000000..2eb6279f6 --- /dev/null +++ b/spec/models/site_customization/content_block_spec.rb @@ -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