From b35683f75e8f7b18df68305c12fd4cb19d296e20 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Gonz=C3=A1lez?= Date: Mon, 13 Mar 2017 12:11:45 +0100 Subject: [PATCH 01/13] Implement Sandbox --- app/controllers/sandbox_controller.rb | 45 +++++++++++++++++++++++++++ app/views/sandbox/index.html.erb | 13 ++++++++ config/routes.rb | 5 +++ 3 files changed, 63 insertions(+) create mode 100644 app/controllers/sandbox_controller.rb create mode 100644 app/views/sandbox/index.html.erb diff --git a/app/controllers/sandbox_controller.rb b/app/controllers/sandbox_controller.rb new file mode 100644 index 000000000..12b5dd91e --- /dev/null +++ b/app/controllers/sandbox_controller.rb @@ -0,0 +1,45 @@ +class SandboxController < ApplicationController + skip_authorization_check + + layout :set_layout + + helper_method(:namespace) + + def index + @templates = Dir.glob(Rails.root.join('app/views/sandbox/*.html.erb').to_s).map do |filename| + filename = File.basename(filename, File.extname(filename)) + filename unless filename.starts_with?('_') || filename == 'index.html' + end.compact + end + + def show + if params[:template].index('.') # CVE-2014-0130 + render :action => "index" + elsif lookup_context.exists?("sandbox/#{params[:template]}") + if params[:template] == "index" + render :action => "index" + else + render "sandbox/#{params[:template]}" + end + + elsif lookup_context.exists?("sandbox/#{params[:template]}/index") + render "sandbox/#{params[:template]}/index" + else + render :action => "index" + end + end + + private + + def set_layout + if params[:template] && params[:template].split("_").first == "admin" + "admin" + else + "application" + end + end + + def namespace + "admin" + end +end diff --git a/app/views/sandbox/index.html.erb b/app/views/sandbox/index.html.erb new file mode 100644 index 000000000..9d6303698 --- /dev/null +++ b/app/views/sandbox/index.html.erb @@ -0,0 +1,13 @@ +
+
+
+

Welcome to sandbox

+ +
    + <% @templates.each do |template| %> +
  • <%= link_to template, "/sandbox/" + template %>
  • + <% end %> +
+
+
+
diff --git a/config/routes.rb b/config/routes.rb index b66410e22..b1a6d57b2 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,5 +1,10 @@ Rails.application.routes.draw do + if Rails.env.development? || Rails.env.staging? + get '/sandbox' => 'sandbox#index' + get '/sandbox/*template' => 'sandbox#show' + end + devise_for :users, controllers: { registrations: 'users/registrations', sessions: 'users/sessions', From 75554e5e4f6253bb2afcacc15d475dbf258b51de Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Gonz=C3=A1lez?= Date: Mon, 13 Mar 2017 15:13:47 +0100 Subject: [PATCH 02/13] Implement markup --- app/assets/stylesheets/admin.scss | 10 ++++ app/views/sandbox/admin_cms.html.erb | 62 +++++++++++++++++++++++ app/views/sandbox/admin_cms_page.html.erb | 58 +++++++++++++++++++++ 3 files changed, 130 insertions(+) create mode 100644 app/views/sandbox/admin_cms.html.erb create mode 100644 app/views/sandbox/admin_cms_page.html.erb diff --git a/app/assets/stylesheets/admin.scss b/app/assets/stylesheets/admin.scss index 90dee613a..252cef324 100644 --- a/app/assets/stylesheets/admin.scss +++ b/app/assets/stylesheets/admin.scss @@ -403,3 +403,13 @@ table.investment-projects-summary { white-space: nowrap; } } + +// 05. CMS +// -------------- +.cms_page_list { + + [class^="icon-"] { + padding-right: $menu-icon-spacing; + vertical-align: middle; + } +} diff --git a/app/views/sandbox/admin_cms.html.erb b/app/views/sandbox/admin_cms.html.erb new file mode 100644 index 000000000..26cc96f5c --- /dev/null +++ b/app/views/sandbox/admin_cms.html.erb @@ -0,0 +1,62 @@ +Crear nueva página +

Editar páginas

+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
NombreCreadaÚltima actualizaciónEstado
+ Política de privacidad + + Hace 20 días + + Hace 15 días + + Publicada + + + Ver página + + + Borrar página +
+ FAQ + + Hace 6 días + + Hace 3 días + + + Borrador + + + Ver página + + + Borrar página +
diff --git a/app/views/sandbox/admin_cms_page.html.erb b/app/views/sandbox/admin_cms_page.html.erb new file mode 100644 index 000000000..625317d35 --- /dev/null +++ b/app/views/sandbox/admin_cms_page.html.erb @@ -0,0 +1,58 @@ + + + + Volver + + +
+
+

Editar Política de privacidad

+ +
+ + + + + + + + + +
+ + +
+
+
+
+
+

Opciones

+ + + +
+ +

Estado

+ + +
+ + +
+ +
+ + +
+ + +
+ +
+
+ + From 019037ebddde12e59c7824432fe05de42b03c0bb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mart=C3=ADn=20Gonz=C3=A1lez?= Date: Mon, 13 Mar 2017 15:21:22 +0100 Subject: [PATCH 03/13] Add delete page button --- app/views/sandbox/admin_cms_page.html.erb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/app/views/sandbox/admin_cms_page.html.erb b/app/views/sandbox/admin_cms_page.html.erb index 625317d35..ea65176b8 100644 --- a/app/views/sandbox/admin_cms_page.html.erb +++ b/app/views/sandbox/admin_cms_page.html.erb @@ -4,7 +4,10 @@ Volver + +
+

Editar Política de privacidad

@@ -19,8 +22,8 @@
- - + +
From 255b57cc8520892a4b80a8182bb9acc6ea728ca9 Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Fri, 17 Mar 2017 12:20:36 +0100 Subject: [PATCH 04/13] Admin for custom pages --- .../site_customization/base_controller.rb | 10 +++ .../site_customization/pages_controller.rb | 44 +++++++++++++ app/models/abilities/administrator.rb | 2 + app/models/site_customization.rb | 5 ++ app/models/site_customization/page.rb | 14 +++++ app/views/admin/_menu.html.erb | 6 ++ .../site_customization/pages/_form.html.erb | 52 ++++++++++++++++ .../site_customization/pages/edit.html.erb | 15 +++++ .../site_customization/pages/index.html.erb | 52 ++++++++++++++++ .../site_customization/pages/new.html.erb | 14 +++++ config/locales/activerecord.en.yml | 17 +++++ config/locales/activerecord.es.yml | 17 +++++ config/locales/admin.en.yml | 33 ++++++++++ config/locales/admin.es.yml | 33 ++++++++++ config/routes.rb | 4 ++ ...6174351_create_site_customization_pages.rb | 15 +++++ db/schema.rb | 14 ++++- spec/factories.rb | 18 ++++++ .../admin/site_customization/pages_spec.rb | 62 +++++++++++++++++++ spec/models/site_customization/page_spec.rb | 14 +++++ 20 files changed, 440 insertions(+), 1 deletion(-) create mode 100644 app/controllers/admin/site_customization/base_controller.rb create mode 100644 app/controllers/admin/site_customization/pages_controller.rb create mode 100644 app/models/site_customization.rb create mode 100644 app/models/site_customization/page.rb create mode 100644 app/views/admin/site_customization/pages/_form.html.erb create mode 100644 app/views/admin/site_customization/pages/edit.html.erb create mode 100644 app/views/admin/site_customization/pages/index.html.erb create mode 100644 app/views/admin/site_customization/pages/new.html.erb create mode 100644 db/migrate/20170316174351_create_site_customization_pages.rb create mode 100644 spec/features/admin/site_customization/pages_spec.rb create mode 100644 spec/models/site_customization/page_spec.rb diff --git a/app/controllers/admin/site_customization/base_controller.rb b/app/controllers/admin/site_customization/base_controller.rb new file mode 100644 index 000000000..18422f66e --- /dev/null +++ b/app/controllers/admin/site_customization/base_controller.rb @@ -0,0 +1,10 @@ +class Admin::SiteCustomization::BaseController < Admin::BaseController + helper_method :namespace + + private + + def namespace + "admin" + end + +end diff --git a/app/controllers/admin/site_customization/pages_controller.rb b/app/controllers/admin/site_customization/pages_controller.rb new file mode 100644 index 000000000..0b838054e --- /dev/null +++ b/app/controllers/admin/site_customization/pages_controller.rb @@ -0,0 +1,44 @@ +class Admin::SiteCustomization::PagesController < Admin::SiteCustomization::BaseController + load_and_authorize_resource :page, class: "SiteCustomization::Page" + + def index + @pages = SiteCustomization::Page.order('slug').page(params[:page]) + end + + def create + if @page.save + redirect_to admin_site_customization_pages_path, notice: t('admin.site_customization.pages.create.notice', link: @page.slug.html_safe) + else + flash.now[:error] = t('admin.site_customization.pages.create.error') + render :new + end + end + + def update + if @page.update(page_params) + redirect_to admin_site_customization_pages_path, notice: t('admin.site_customization.pages.update.notice', link: @page.slug.html_safe) + else + flash.now[:error] = t('admin.site_customization.pages.update.error') + render :edit + end + end + + def destroy + @page.destroy + redirect_to admin_site_customization_pages_path, notice: t('admin.site_customization.pages.destroy.notice') + end + + private + + def page_params + params.require(:site_customization_page).permit( + :slug, + :title, + :subtitle, + :content, + :more_info_flag, + :print_content_flag, + :status + ) + end +end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 8e721b2b8..8df9270a3 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -51,6 +51,8 @@ module Abilities can [:search, :edit, :update, :create, :index, :destroy], Banner can [:index, :create, :edit, :update, :destroy], Geozone + + can :manage, SiteCustomization::Page end end end diff --git a/app/models/site_customization.rb b/app/models/site_customization.rb new file mode 100644 index 000000000..e5d2f2137 --- /dev/null +++ b/app/models/site_customization.rb @@ -0,0 +1,5 @@ +module SiteCustomization + def self.table_name_prefix + 'site_customization_' + end +end diff --git a/app/models/site_customization/page.rb b/app/models/site_customization/page.rb new file mode 100644 index 000000000..565e6352a --- /dev/null +++ b/app/models/site_customization/page.rb @@ -0,0 +1,14 @@ +class SiteCustomization::Page < ActiveRecord::Base + VALID_STATUSES = %w(draft published) + + validates :slug, uniqueness: { case_sensitive: false }, + format: { with: /\A[0-9a-zA-Z\-_]*\Z/, message: :slug_format } + validates :title, presence: true + validates :status, presence: true, inclusion: { in: VALID_STATUSES } + + scope :published, -> { where(status: 'published').order('id DESC') } + + def url + "/#{slug}" + end +end diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index d603dbf16..448da1662 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -122,5 +122,11 @@ <%= t("admin.menu.stats") %> <% end %> + +
  • > + <%= link_to admin_site_customization_pages_path do %> + <%= t("admin.menu.site_customization.pages") %> + <% end %> +
  • diff --git a/app/views/admin/site_customization/pages/_form.html.erb b/app/views/admin/site_customization/pages/_form.html.erb new file mode 100644 index 000000000..3881885d2 --- /dev/null +++ b/app/views/admin/site_customization/pages/_form.html.erb @@ -0,0 +1,52 @@ +<%= form_for [:admin, @page], html: {class: "edit_page", data: {watch_changes: true}} do |f| %> + + <% if @page.errors.any? %> + +
    + + + + <%= @page.errors.count %> + <%= t("admin.site_customization.pages.errors.form.error", count: @page.errors.count) %> + +
    + + <% end %> + +
    + + <%= f.label :title %> + <%= f.text_field :title, label: false %> + + <%= f.label :subtitle %> + <%= f.text_field :subtitle, label: false, size: 80, maxlength: 80 %> + + <%= f.label :slug %> + <%= f.text_field :slug, label: false, size: 80, maxlength: 80 %> + +
    + <%= f.label :content %> + <%= f.cktext_area :content, label: false, cols: 80, rows: 10, ckeditor: { language: I18n.locale } %> +
    +
    +
    +
    +

    <%= t("admin.site_customization.pages.form.options") %>

    + <%= f.check_box :more_info_flag %> + <%= f.check_box :print_content_flag %> +
    + +

    <%= f.label :status %>

    + <% ::SiteCustomization::Page::VALID_STATUSES.each do |status| %> + <%= f.radio_button :status, status, label: false %> + <%= f.label "status_#{status}", t("admin.site_customization.pages.status_#{status}") %> +
    + <% end %> + + <%= f.submit class: "button success" %> +
    + +
    +<% end %> diff --git a/app/views/admin/site_customization/pages/edit.html.erb b/app/views/admin/site_customization/pages/edit.html.erb new file mode 100644 index 000000000..c92933cbf --- /dev/null +++ b/app/views/admin/site_customization/pages/edit.html.erb @@ -0,0 +1,15 @@ +<% provide :title do %> + Admin - <%= t("admin.menu.site_customization.pages") %> - <%= @page.title %> +<% end %> + +<%= link_to admin_site_customization_pages_path, class: "back" do %> + + <%= t("admin.site_customization.pages.edit.back") %> +<% end %> + +<%= button_to t("admin.site_customization.pages.index.delete"), admin_site_customization_page_path(@page), method: :delete, class: "button hollow alert float-right margin-right" %> + +
    +

    <%= t("admin.site_customization.pages.edit.title", page_title: @page.title) %>

    + <%= render 'form' %> +
    diff --git a/app/views/admin/site_customization/pages/index.html.erb b/app/views/admin/site_customization/pages/index.html.erb new file mode 100644 index 000000000..356a1813b --- /dev/null +++ b/app/views/admin/site_customization/pages/index.html.erb @@ -0,0 +1,52 @@ +<% provide :title do %> + Admin - <%= t("admin.menu.site_customization.pages") %> +<% end %> + +
    +
    +
    +

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

    +
    +
    + <%= link_to t("admin.site_customization.pages.index.create"), new_admin_site_customization_page_path, class: "button" %> +
    +
    + +

    <%= page_entries_info @pages %>

    + + + + + + + + + + + + + + <% @pages.each do |page| %> + + + + + + + + + <% end %> + +
    <%= t("admin.site_customization.pages.page.title") %><%= t("admin.site_customization.pages.page.created_at") %><%= t("admin.site_customization.pages.page.updated_at") %><%= t("admin.site_customization.pages.page.status") %>
    + <%= link_to page.title, edit_admin_site_customization_page_path(page) %> + <%= I18n.l page.created_at, format: :short %><%= I18n.l page.created_at, format: :short %><%= t("admin.legislation.processes.process.status_#{page.status}") %> + + <%= link_to t("admin.site_customization.pages.index.see_page"), page.url %> + + + <%= link_to t("admin.site_customization.pages.index.delete"), admin_site_customization_page_path(page), method: :delete %> +
    + + <%= paginate @pages %> + +
    diff --git a/app/views/admin/site_customization/pages/new.html.erb b/app/views/admin/site_customization/pages/new.html.erb new file mode 100644 index 000000000..43a86d108 --- /dev/null +++ b/app/views/admin/site_customization/pages/new.html.erb @@ -0,0 +1,14 @@ +<% provide :title do %> + Admin - <%= t("admin.menu.site_customization.pages") %> - <%= t("admin.site_customization.pages.new.title") %> +<% end %> + +<%= link_to admin_site_customization_pages_path, class: "back" do %> + + <%= t("admin.site_customization.pages.new.back") %> +<% end %> + +
    +

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

    + <%= render 'form' %> +
    + diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index 04c5cc9d0..e8354b88e 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -40,6 +40,9 @@ en: spending_proposal: one: "Spending proposal" other: "Spending proposals" + site_customization/page: + one: Custom page + other: Custom pages attributes: budget: name: "Name" @@ -103,6 +106,16 @@ en: signable_type: "Signable type" signable_id: "Signable ID" document_numbers: "Documents numbers" + site_customization/page: + content: Content + created_at: Created at + subtitle: Subtitle + slug: Slug + status: Status + title: Title + updated_at: Updated at + more_info_flag: Show in more information page + print_content_flag: Print content button errors: models: user: @@ -134,3 +147,7 @@ en: document_number: not_in_census: 'Not verified by Census' already_voted: 'Already voted this proposal' + site_customization/page: + attributes: + slug: + slug_format: "must be letters, numbers, _ and -" diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index 542406d0a..32b26223b 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -40,6 +40,9 @@ es: spending_proposal: one: "Propuesta de inversión" other: "Propuestas de inversión" + site_customization/page: + one: Página + other: Páginas attributes: budget: name: "Nombre" @@ -98,6 +101,16 @@ es: signable_type: "Tipo de hoja de firmas" signable_id: "ID Propuesta ciudadana/Propuesta inversión" document_numbers: "Números de documentos" + site_customization/page: + content: Contenido + created_at: Creada + subtitle: Subtítulo + slug: Slug + status: Estado + title: Título + 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 errors: models: user: @@ -129,3 +142,7 @@ es: document_number: not_in_census: 'No verificado por Padrón' already_voted: 'Ya ha votado esta propuesta' + site_customization/page: + attributes: + slug: + slug_format: "deber ser letras, números, _ y -" diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 460319748..d44179ce8 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -207,6 +207,8 @@ en: spending_proposals: Spending proposals stats: Statistics signature_sheets: Signature Sheets + site_customization: + pages: Custom Pages moderators: index: title: Moderators @@ -475,3 +477,34 @@ en: phone_not_given: Phone not given sms_code_not_confirmed: Has not confirmed the sms code title: Incomplete verifications + site_customization: + pages: + create: + notice: 'Page created successfully.' + error: Process couldn't be created + update: + notice: 'Page updated successfully.' + error: Page couldn't be updated + destroy: + notice: Page deleted successfully + edit: + title: Editing %{page_title} + back: Back + errors: + form: + error: Error + form: + options: Options + index: + create: Create new page + delete: Delete + title: Custom Pages + see_page: See page + new: + back: Back + title: Create new custom page + page: + created_at: Created at + status: Status + title: Title + updated_at: Updated at diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 7d6438416..f93433546 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -207,6 +207,8 @@ es: spending_proposals: Propuestas de inversión stats: Estadísticas signature_sheets: Hojas de firmas + site_customization: + pages: Páginas moderators: index: title: Moderadores @@ -475,3 +477,34 @@ es: phone_not_given: No ha dado su teléfono sms_code_not_confirmed: No ha introducido su código de seguridad title: Verificaciones incompletas + site_customization: + pages: + create: + notice: 'Página creada correctamente.' + error: No se ha podido crear la página + update: + notice: 'Página actualizada correctamente.s' + error: No se ha podido actualizar la página + destroy: + notice: Página eliminada correctamente + edit: + title: Editar %{page_title} + back: Volver + errors: + form: + error: Error + form: + options: Opciones + index: + create: Crear nueva página + delete: Borrar + title: Páginas + see_page: Ver página + new: + back: Back + title: Página nueva + page: + created_at: Creada + status: Estado + title: Título + updated_at: Última actualización diff --git a/config/routes.rb b/config/routes.rb index b1a6d57b2..e31bd86a0 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -222,6 +222,10 @@ Rails.application.routes.draw do end resources :geozones, only: [:index, :new, :create, :edit, :update, :destroy] + + namespace :site_customization do + resources :pages + end end namespace :moderation do diff --git a/db/migrate/20170316174351_create_site_customization_pages.rb b/db/migrate/20170316174351_create_site_customization_pages.rb new file mode 100644 index 000000000..3c4fbe846 --- /dev/null +++ b/db/migrate/20170316174351_create_site_customization_pages.rb @@ -0,0 +1,15 @@ +class CreateSiteCustomizationPages < ActiveRecord::Migration + def change + create_table :site_customization_pages do |t| + t.string :slug, null: false + t.string :title, null: false + t.string :subtitle + t.text :content + t.boolean :more_info_flag + t.boolean :print_content_flag + t.string :status, default: 'draft' + + t.timestamps null: false + end + end +end diff --git a/db/schema.rb b/db/schema.rb index fb563c8db..0b38a4196 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: 20170114154421) do +ActiveRecord::Schema.define(version: 20170316174351) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -439,6 +439,18 @@ ActiveRecord::Schema.define(version: 20170114154421) do t.datetime "updated_at" end + create_table "site_customization_pages", force: :cascade do |t| + t.string "slug", null: false + t.string "title", null: false + t.string "subtitle" + t.text "content" + t.boolean "more_info_flag" + t.boolean "print_content_flag" + t.string "status", default: "draft" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + create_table "spending_proposals", force: :cascade do |t| t.string "title" t.text "description" diff --git a/spec/factories.rb b/spec/factories.rb index e058adf15..20a1f463c 100644 --- a/spec/factories.rb +++ b/spec/factories.rb @@ -450,4 +450,22 @@ FactoryGirl.define do signature_sheet sequence(:document_number) { |n| "#{n}A" } end + + factory :site_customization_page, class: 'SiteCustomization::Page' do + slug "example-page" + title "Example page" + subtitle "About an example" + content "This page is about..." + more_info_flag false + print_content_flag false + status 'draft' + + trait :published do + status "published" + end + + trait :display_in_more_info do + more_info_flag true + end + end end diff --git a/spec/features/admin/site_customization/pages_spec.rb b/spec/features/admin/site_customization/pages_spec.rb new file mode 100644 index 000000000..b9ebeb273 --- /dev/null +++ b/spec/features/admin/site_customization/pages_spec.rb @@ -0,0 +1,62 @@ +require 'rails_helper' + +feature 'Admin custom pages' do + + background do + admin = create(:administrator) + login_as(admin.user) + end + + context "Index" do + scenario 'Displaying custom pages' do + custom_page = create(:site_customization_page) + visit admin_site_customization_pages_path + + expect(page).to have_content(custom_page.title) + end + end + + context 'Create' do + scenario 'Valid custom page' do + visit admin_root_path + + within('#side_menu') do + click_link "Custom Pages" + end + + expect(page).to_not have_content 'An example custom page' + + click_link "Create new page" + + fill_in 'site_customization_page_title', with: 'An example custom page' + fill_in 'site_customization_page_subtitle', with: 'Page subtitle' + fill_in 'site_customization_page_slug', with: 'example-page' + fill_in 'site_customization_page_content', with: 'This page is about...' + + click_button 'Create Custom page' + + expect(page).to have_content 'An example custom page' + end + end + + context 'Update' do + scenario 'Valid custom page' do + custom_page = create(:site_customization_page, title: 'An example custom page') + visit admin_root_path + + within('#side_menu') do + click_link "Custom Pages" + end + + click_link "An example custom page" + + expect(page).to have_selector("h2", text: "An example custom page") + + fill_in 'site_customization_page_title', with: 'Another example custom page' + click_button "Update Custom page" + + expect(page).to have_content "Page updated successfully" + expect(page).to have_content 'Another example custom page' + end + end +end diff --git a/spec/models/site_customization/page_spec.rb b/spec/models/site_customization/page_spec.rb new file mode 100644 index 000000000..2868f62d1 --- /dev/null +++ b/spec/models/site_customization/page_spec.rb @@ -0,0 +1,14 @@ +require 'rails_helper' + +RSpec.describe SiteCustomization::Page, type: :model do + let(:custom_page) { build(:site_customization_page) } + + it "should be valid" do + expect(custom_page).to be_valid + end + + it "is invalid if slug has symbols" do + custom_page = build(:site_customization_page, slug: "as/as*la") + expect(custom_page).to be_invalid + end +end From 54fab919e51357c756ec449aa1ee88b22267ad5a Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Fri, 17 Mar 2017 13:36:00 +0100 Subject: [PATCH 05/13] Show custom pages in public site --- app/controllers/pages_controller.rb | 6 +- app/models/site_customization/page.rb | 1 + .../site_customization/pages/index.html.erb | 17 +-- app/views/pages/custom_page.html.erb | 15 +++ app/views/pages/more_info/_other.html.erb | 4 + config/i18n-tasks.yml | 1 + config/locales/admin.en.yml | 2 + config/locales/admin.es.yml | 2 + config/routes.rb | 2 +- .../admin/site_customization/pages_spec.rb | 53 +++++---- .../site_customization/custom_pages_spec.rb | 102 ++++++++++++++++++ 11 files changed, 167 insertions(+), 38 deletions(-) create mode 100644 app/views/pages/custom_page.html.erb create mode 100644 spec/features/site_customization/custom_pages_spec.rb diff --git a/app/controllers/pages_controller.rb b/app/controllers/pages_controller.rb index 03f62925a..81d6e8dbd 100644 --- a/app/controllers/pages_controller.rb +++ b/app/controllers/pages_controller.rb @@ -2,7 +2,11 @@ class PagesController < ApplicationController skip_authorization_check def show - render action: params[:id] + if @custom_page = SiteCustomization::Page.published.find_by(slug: params[:id]) + render action: :custom_page + else + render action: params[:id] + end rescue ActionView::MissingTemplate head 404 end diff --git a/app/models/site_customization/page.rb b/app/models/site_customization/page.rb index 565e6352a..ea3003465 100644 --- a/app/models/site_customization/page.rb +++ b/app/models/site_customization/page.rb @@ -7,6 +7,7 @@ class SiteCustomization::Page < ActiveRecord::Base validates :status, presence: true, inclusion: { in: VALID_STATUSES } scope :published, -> { where(status: 'published').order('id DESC') } + scope :with_more_info_flag, -> { where(status: 'published', more_info_flag: true).order('id ASC') } def url "/#{slug}" diff --git a/app/views/admin/site_customization/pages/index.html.erb b/app/views/admin/site_customization/pages/index.html.erb index 356a1813b..eef3370e6 100644 --- a/app/views/admin/site_customization/pages/index.html.erb +++ b/app/views/admin/site_customization/pages/index.html.erb @@ -2,19 +2,12 @@ Admin - <%= t("admin.menu.site_customization.pages") %> <% end %> -
    -
    -
    -

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

    -
    -
    - <%= link_to t("admin.site_customization.pages.index.create"), new_admin_site_customization_page_path, class: "button" %> -
    -
    +<%= link_to t("admin.site_customization.pages.index.create"), new_admin_site_customization_page_path, class: "button float-right margin-right" %> +

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

    <%= page_entries_info @pages %>

    - +
    @@ -33,7 +26,7 @@ - +
    <%= t("admin.site_customization.pages.page.title") %> <%= I18n.l page.created_at, format: :short %> <%= I18n.l page.created_at, format: :short %><%= t("admin.legislation.processes.process.status_#{page.status}") %><%= t("admin.site_customization.pages.page.status_#{page.status}") %> <%= link_to t("admin.site_customization.pages.index.see_page"), page.url %> @@ -48,5 +41,3 @@
    <%= paginate @pages %> - -
    diff --git a/app/views/pages/custom_page.html.erb b/app/views/pages/custom_page.html.erb new file mode 100644 index 000000000..f14eba7d9 --- /dev/null +++ b/app/views/pages/custom_page.html.erb @@ -0,0 +1,15 @@ +<% provide :title do %><%= @custom_page.title %><% end %> + +
    + +
    +

    <%= @custom_page.title %>

    +

    <%= @custom_page.subtitle %>

    + + <%= raw @custom_page.content %> +
    + +
    + <%= render '/shared/print' if @custom_page.print_content_flag %> +
    +
    diff --git a/app/views/pages/more_info/_other.html.erb b/app/views/pages/more_info/_other.html.erb index d0718294c..5501c9e31 100644 --- a/app/views/pages/more_info/_other.html.erb +++ b/app/views/pages/more_info/_other.html.erb @@ -4,4 +4,8 @@
  • <%= link_to t("pages.more_info.other.how_to_use", org_name: setting['org_name']), faq_path %>
  • <%= link_to t("pages.more_info.other.facts"), participation_facts_path %>
  • <%= link_to t("pages.more_info.other.world"), participation_world_path %>
  • + + <% SiteCustomization::Page.with_more_info_flag.each do |custom_page| %> +
  • <%= link_to custom_page.title, page_path(custom_page.slug) %>
  • + <% end %> diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index f95f0a550..85844f948 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -152,6 +152,7 @@ ignore_unused: - 'views.pagination.*' # kaminari - 'shared.suggest.*' - 'invisible_captcha.*' + - 'admin.site_customization.pages.page.status_*' # - '{devise,kaminari,will_paginate}.*' # - 'simple_form.{yes,no}' # - 'simple_form.{placeholders,hints,labels}.*' diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index d44179ce8..be2f9280e 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -508,3 +508,5 @@ en: status: Status title: Title updated_at: Updated at + status_draft: Draft + status_published: Published diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index f93433546..7b14bf90a 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -508,3 +508,5 @@ es: status: Estado title: Título updated_at: Última actualización + status_draft: Borrador + status_published: Publicada diff --git a/config/routes.rb b/config/routes.rb index e31bd86a0..af9ac8a08 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -224,7 +224,7 @@ Rails.application.routes.draw do resources :geozones, only: [:index, :new, :create, :edit, :update, :destroy] namespace :site_customization do - resources :pages + resources :pages, except: [:show] end end diff --git a/spec/features/admin/site_customization/pages_spec.rb b/spec/features/admin/site_customization/pages_spec.rb index b9ebeb273..20b817f50 100644 --- a/spec/features/admin/site_customization/pages_spec.rb +++ b/spec/features/admin/site_customization/pages_spec.rb @@ -1,50 +1,48 @@ require 'rails_helper' -feature 'Admin custom pages' do +feature "Admin custom pages" do background do admin = create(:administrator) login_as(admin.user) end - context "Index" do - scenario 'Displaying custom pages' do - custom_page = create(:site_customization_page) - visit admin_site_customization_pages_path + scenario "Index" do + custom_page = create(:site_customization_page) + visit admin_site_customization_pages_path - expect(page).to have_content(custom_page.title) - end + expect(page).to have_content(custom_page.title) end - context 'Create' do - scenario 'Valid custom page' do + context "Create" do + scenario "Valid custom page" do visit admin_root_path - within('#side_menu') do + within("#side_menu") do click_link "Custom Pages" end - expect(page).to_not have_content 'An example custom page' + expect(page).to_not have_content "An example custom page" click_link "Create new page" - fill_in 'site_customization_page_title', with: 'An example custom page' - fill_in 'site_customization_page_subtitle', with: 'Page subtitle' - fill_in 'site_customization_page_slug', with: 'example-page' - fill_in 'site_customization_page_content', with: 'This page is about...' + fill_in "site_customization_page_title", with: "An example custom page" + fill_in "site_customization_page_subtitle", with: "Page subtitle" + fill_in "site_customization_page_slug", with: "example-page" + fill_in "site_customization_page_content", with: "This page is about..." - click_button 'Create Custom page' + click_button "Create Custom page" - expect(page).to have_content 'An example custom page' + expect(page).to have_content "An example custom page" end end - context 'Update' do - scenario 'Valid custom page' do - custom_page = create(:site_customization_page, title: 'An example custom page') + context "Update" do + scenario "Valid custom page" do + custom_page = create(:site_customization_page, title: "An example custom page") visit admin_root_path - within('#side_menu') do + within("#side_menu") do click_link "Custom Pages" end @@ -52,11 +50,20 @@ feature 'Admin custom pages' do expect(page).to have_selector("h2", text: "An example custom page") - fill_in 'site_customization_page_title', with: 'Another example custom page' + fill_in "site_customization_page_title", with: "Another example custom page" click_button "Update Custom page" expect(page).to have_content "Page updated successfully" - expect(page).to have_content 'Another example custom page' + expect(page).to have_content "Another example custom page" end end + + scenario "Index" do + custom_page = create(:site_customization_page, title: "An example custom page") + visit edit_admin_site_customization_page_path(custom_page) + + click_button "Delete" + + expect(page).to_not have_content("An example custom page") + end end diff --git a/spec/features/site_customization/custom_pages_spec.rb b/spec/features/site_customization/custom_pages_spec.rb new file mode 100644 index 000000000..2e2fac84a --- /dev/null +++ b/spec/features/site_customization/custom_pages_spec.rb @@ -0,0 +1,102 @@ +require 'rails_helper' + +feature "Custom Pages" do + context "Override existing page" do + scenario "See default content when custom page is not published" do + custom_page = create(:site_customization_page, + slug: "conditions", + title: "Custom conditions", + content: "New text for conditions page", + print_content_flag: true + ) + + visit custom_page.url + + expect(page).to have_title("Terms of use") + expect(page).to have_selector("h1", text: "Terms and conditions of use") + expect(page).to have_content("Página de información sobre las condiciones de uso, privacidad y protección de datos personales.") + expect(page).to have_content("Print this info") + end + + scenario "See custom content when custom page is published" do + custom_page = create(:site_customization_page, :published, + slug: "conditions", + title: "Custom conditions", + content: "New text for conditions page", + print_content_flag: true + ) + + visit custom_page.url + + expect(page).to have_title("Custom conditions") + expect(page).to have_selector("h1", text: "Custom conditions") + expect(page).to have_content("New text for conditions page") + expect(page).to have_content("Print this info") + end + end + + context "New custom page" do + context "Draft" do + scenario "See page" do + custom_page = create(:site_customization_page, + slug: "other-slug", + title: "Custom page", + content: "Text for new custom page", + print_content_flag: false + ) + + visit custom_page.url + + expect(page.status_code).to eq(404) + end + end + + context "Published" do + scenario "See page" do + custom_page = create(:site_customization_page, :published, + slug: "other-slug", + title: "Custom page", + content: "Text for new custom page", + print_content_flag: false + ) + + visit custom_page.url + + expect(page).to have_title("Custom page") + expect(page).to have_selector("h1", text: "Custom page") + expect(page).to have_content("Text for new custom page") + expect(page).to_not have_content("Print this info") + end + + scenario "Listed in more information page" do + custom_page = create(:site_customization_page, :published, + slug: "another-slug", title: "Another custom page", + subtitle: "Subtitle for custom page", + more_info_flag: true + ) + + visit more_info_path + + expect(page).to have_content("Another custom page") + end + + scenario "Not listed in more information page" do + custom_page = create(:site_customization_page, :published, + slug: "another-slug", title: "Another custom page", + subtitle: "Subtitle for custom page", + more_info_flag: false + ) + + visit more_info_path + + expect(page).to_not have_content("Another custom page") + + visit custom_page.url + + expect(page).to have_title("Another custom page") + expect(page).to have_selector("h1", text: "Another custom page") + expect(page).to have_content("Subtitle for custom page") + end + end + end +end From 8143fe10370edb1eb2edd5ca31ff34576d157097 Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Thu, 23 Mar 2017 18:03:22 +0100 Subject: [PATCH 06/13] Site customization: images uploads --- Gemfile | 2 + Gemfile.lock | 10 ++- .../site_customization/images_controller.rb | 43 ++++++++++++ .../site_customization/pages_controller.rb | 4 +- app/helpers/application_helper.rb | 4 ++ app/models/abilities/administrator.rb | 1 + app/models/site_customization/image.rb | 48 ++++++++++++++ app/views/admin/_menu.html.erb | 6 ++ .../site_customization/images/index.html.erb | 25 +++++++ app/views/layouts/_admin_header.html.erb | 4 +- app/views/layouts/_header.html.erb | 2 +- app/views/layouts/application.html.erb | 2 +- app/views/layouts/devise.html.erb | 2 +- app/views/layouts/management.html.erb | 2 +- .../shared/_social_media_meta_tags.html.erb | 4 +- app/views/welcome/index.html.erb | 2 +- config/locales/activerecord.en.yml | 8 +++ config/locales/activerecord.es.yml | 8 +++ config/locales/admin.en.yml | 16 ++++- config/locales/admin.es.yml | 18 ++++- config/routes.rb | 1 + ...145702_create_site_customization_images.rb | 11 ++++ db/schema.rb | 14 +++- .../admin/site_customization/images_spec.rb | 62 ++++++++++++++++++ .../admin/site_customization/pages_spec.rb | 4 +- spec/fixtures/files/logo_header.png | Bin 0 -> 463 bytes spec/fixtures/files/social-media-icon.png | Bin 0 -> 3353 bytes 27 files changed, 283 insertions(+), 20 deletions(-) create mode 100644 app/controllers/admin/site_customization/images_controller.rb create mode 100644 app/models/site_customization/image.rb create mode 100644 app/views/admin/site_customization/images/index.html.erb create mode 100644 db/migrate/20170322145702_create_site_customization_images.rb create mode 100644 spec/features/admin/site_customization/images_spec.rb create mode 100644 spec/fixtures/files/logo_header.png create mode 100644 spec/fixtures/files/social-media-icon.png diff --git a/Gemfile b/Gemfile index f9c2f54e5..39dee65f8 100644 --- a/Gemfile +++ b/Gemfile @@ -65,6 +65,8 @@ gem 'browser' gem 'turnout', '~> 2.4.0' gem 'redcarpet', '~> 3.4.0' +gem 'paperclip' + group :development, :test do # Call 'byebug' anywhere in the code to stop execution and get a debugger console gem 'byebug' diff --git a/Gemfile.lock b/Gemfile.lock index 6c117ea77..67ab5a78b 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -238,6 +238,7 @@ GEM mime-types (3.1) mime-types-data (~> 3.2015) mime-types-data (3.2016.0521) + mimemagic (0.3.2) mini_portile2 (2.1.0) minitest (5.10.1) multi_json (1.12.1) @@ -277,6 +278,12 @@ GEM omniauth-oauth (~> 1.1) rack orm_adapter (0.5.0) + paperclip (5.1.0) + activemodel (>= 4.2.0) + activesupport (>= 4.2.0) + cocaine (~> 0.5.5) + mime-types + mimemagic (~> 0.3.0) paranoia (2.2.1) activerecord (>= 4.0, < 5.1) parser (2.4.0.0) @@ -504,6 +511,7 @@ DEPENDENCIES omniauth-facebook (~> 4.0.0) omniauth-google-oauth2 (~> 0.4.0) omniauth-twitter + paperclip paranoia (~> 2.2.1) pg (~> 0.20.0) pg_search @@ -533,4 +541,4 @@ DEPENDENCIES whenever BUNDLED WITH - 1.13.7 + 1.14.6 diff --git a/app/controllers/admin/site_customization/images_controller.rb b/app/controllers/admin/site_customization/images_controller.rb new file mode 100644 index 000000000..c9f318f41 --- /dev/null +++ b/app/controllers/admin/site_customization/images_controller.rb @@ -0,0 +1,43 @@ +class Admin::SiteCustomization::ImagesController < Admin::SiteCustomization::BaseController + load_and_authorize_resource :image, class: "SiteCustomization::Image" + + def index + @images = SiteCustomization::Image.all_images + end + + def update + if params[:site_customization_image].nil? + redirect_to admin_site_customization_images_path + return + end + + if @image.update(image_params) + redirect_to admin_site_customization_images_path, notice: t('admin.site_customization.images.update.notice') + else + flash.now[:error] = t('admin.site_customization.images.update.error') + + @images = SiteCustomization::Image.all_images + idx = @images.index {|e| e.name == @image.name } + @images[idx] = @image + + render :index + end + end + + def destroy + @image.image = nil + if @image.save + redirect_to admin_site_customization_images_path, notice: t('admin.site_customization.images.destroy.notice') + else + redirect_to admin_site_customization_images_path, notice: t('admin.site_customization.images.destroy.error') + end + end + + private + + def image_params + params.require(:site_customization_image).permit( + :image + ) + end +end diff --git a/app/controllers/admin/site_customization/pages_controller.rb b/app/controllers/admin/site_customization/pages_controller.rb index 0b838054e..4d92a6a1e 100644 --- a/app/controllers/admin/site_customization/pages_controller.rb +++ b/app/controllers/admin/site_customization/pages_controller.rb @@ -7,7 +7,7 @@ class Admin::SiteCustomization::PagesController < Admin::SiteCustomization::Base def create if @page.save - redirect_to admin_site_customization_pages_path, notice: t('admin.site_customization.pages.create.notice', link: @page.slug.html_safe) + redirect_to admin_site_customization_pages_path, notice: t('admin.site_customization.pages.create.notice') else flash.now[:error] = t('admin.site_customization.pages.create.error') render :new @@ -16,7 +16,7 @@ class Admin::SiteCustomization::PagesController < Admin::SiteCustomization::Base def update if @page.update(page_params) - redirect_to admin_site_customization_pages_path, notice: t('admin.site_customization.pages.update.notice', link: @page.slug.html_safe) + redirect_to admin_site_customization_pages_path, notice: t('admin.site_customization.pages.update.notice') else flash.now[:error] = t('admin.site_customization.pages.update.error') render :edit diff --git a/app/helpers/application_helper.rb b/app/helpers/application_helper.rb index 208ed3d3d..c449fa9f4 100644 --- a/app/helpers/application_helper.rb +++ b/app/helpers/application_helper.rb @@ -47,4 +47,8 @@ module ApplicationHelper "".html_safe + t("shared.back") end end + + def image_path_for(filename) + SiteCustomization::Image.image_path_for(filename) || filename + end end diff --git a/app/models/abilities/administrator.rb b/app/models/abilities/administrator.rb index 8df9270a3..c61530772 100644 --- a/app/models/abilities/administrator.rb +++ b/app/models/abilities/administrator.rb @@ -53,6 +53,7 @@ module Abilities can [:index, :create, :edit, :update, :destroy], Geozone can :manage, SiteCustomization::Page + can :manage, SiteCustomization::Image end end end diff --git a/app/models/site_customization/image.rb b/app/models/site_customization/image.rb new file mode 100644 index 000000000..2230a96ce --- /dev/null +++ b/app/models/site_customization/image.rb @@ -0,0 +1,48 @@ +class SiteCustomization::Image < ActiveRecord::Base + VALID_IMAGES = { + "icon_home" => [330, 240], + "logo_header" => [80, 80], + "social-media-icon" => [200, 200], + "apple-touch-icon-200" => [200, 200] + } + + has_attached_file :image + + validates :name, presence: true, uniqueness: true, inclusion: { in: VALID_IMAGES.keys } + validates_attachment_content_type :image, :content_type => ["image/png"] + validate :check_image + + def self.all_images + VALID_IMAGES.keys.map do |image_name| + find_by(name: image_name) || create!(name: image_name.to_s) + end + end + + def self.image_path_for(filename) + image_name = filename.split(".").first + + if i = find_by(name: image_name) + i.image.exists? ? i.image.url : nil + end + end + + def required_width + VALID_IMAGES[name].try(:first) + end + + def required_height + VALID_IMAGES[name].try(:second) + end + + private + + def check_image + return unless image? + + dimensions = Paperclip::Geometry.from_file(image.queued_for_write[:original].path) + + errors.add(:image, :image_width, required_width: required_width) unless dimensions.width == required_width + errors.add(:image, :image_height, required_height: required_height) unless dimensions.height == required_height + end + +end diff --git a/app/views/admin/_menu.html.erb b/app/views/admin/_menu.html.erb index 448da1662..6a48b493b 100644 --- a/app/views/admin/_menu.html.erb +++ b/app/views/admin/_menu.html.erb @@ -128,5 +128,11 @@ <%= t("admin.menu.site_customization.pages") %> <% end %> + +
  • > + <%= link_to admin_site_customization_images_path do %> + <%= t("admin.menu.site_customization.images") %> + <% end %> +
  • diff --git a/app/views/admin/site_customization/images/index.html.erb b/app/views/admin/site_customization/images/index.html.erb new file mode 100644 index 000000000..b9de152d1 --- /dev/null +++ b/app/views/admin/site_customization/images/index.html.erb @@ -0,0 +1,25 @@ +

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

    + + + + <% @images.each do |image| %> + + + + + <% end %> + +
    + <%= image.name %> (<%= image.required_width %>x<%= image.required_height %>) + + <%= form_for([:admin, image], html: { id: "edit_#{dom_id(image)}"}) do |f| %> +
    + <%= image_tag image.image.url if image.image.exists? %> + <%= f.file_field :image, label: false %> +
    +
    + <%= f.submit(t('admin.site_customization.images.index.update'), class: "button hollow") %> + <%= link_to t('admin.site_customization.images.index.delete'), admin_site_customization_image_path(image), method: :delete, class: "button hollow alert" if image.image.exists? %> +
    + <% end %> +
    diff --git a/app/views/layouts/_admin_header.html.erb b/app/views/layouts/_admin_header.html.erb index 095e351d6..72617386c 100644 --- a/app/views/layouts/_admin_header.html.erb +++ b/app/views/layouts/_admin_header.html.erb @@ -18,7 +18,7 @@
    <%= link_to admin_root_path, class: "hide-for-small-only" do %> - <%= image_tag('logo_header.png', class: 'hide-for-small-only float-left', size: '80x80', alt: t("layouts.header.logo")) %> + <%= image_tag(image_path_for('logo_header.png'), class: 'hide-for-small-only float-left', size: '80x80', alt: t("layouts.header.logo")) %> <%= setting['org_name'] %>  | <%= t("admin.dashboard.index.title") %> <% end %> @@ -34,4 +34,4 @@
    - \ No newline at end of file + diff --git a/app/views/layouts/_header.html.erb b/app/views/layouts/_header.html.erb index 9a33662c6..a3162bb8c 100644 --- a/app/views/layouts/_header.html.erb +++ b/app/views/layouts/_header.html.erb @@ -22,7 +22,7 @@
    <%= link_to root_path, class: "hide-for-small-only", accesskey: "0" do %> - <%= image_tag('logo_header.png', class: 'hide-for-small-only float-left', size: '80x80', alt: t("layouts.header.logo")) %> + <%= image_tag(image_path_for('logo_header.png'), class: 'hide-for-small-only float-left', size: '80x80', alt: t("layouts.header.logo")) %> <%= setting['org_name'] %> <% end %>
    diff --git a/app/views/layouts/application.html.erb b/app/views/layouts/application.html.erb index ef4455320..7ae505aad 100644 --- a/app/views/layouts/application.html.erb +++ b/app/views/layouts/application.html.erb @@ -14,7 +14,7 @@ <%= javascript_include_tag "application", 'data-turbolinks-track' => true %> <%= csrf_meta_tags %> <%= favicon_link_tag "favicon.ico" %> - <%= favicon_link_tag "apple-touch-icon-200.png", + <%= favicon_link_tag image_path_for("apple-touch-icon-200.png"), rel: "icon apple-touch-icon", sizes: "200x200", type: "image/png" %> diff --git a/app/views/layouts/devise.html.erb b/app/views/layouts/devise.html.erb index a0e9eaaff..50b84287d 100644 --- a/app/views/layouts/devise.html.erb +++ b/app/views/layouts/devise.html.erb @@ -17,7 +17,7 @@

    <%= link_to root_path do %> - <%= image_tag('logo_header.png', class: 'float-left', alt: t("layouts.header.logo")) %> + <%= image_tag(image_path_for('logo_header.png'), class: 'float-left', alt: t("layouts.header.logo")) %> <%= setting['org_name'] %> <% end %>

    diff --git a/app/views/layouts/management.html.erb b/app/views/layouts/management.html.erb index 8e497bf24..21367d8ab 100644 --- a/app/views/layouts/management.html.erb +++ b/app/views/layouts/management.html.erb @@ -35,7 +35,7 @@
    <%= link_to management_root_path, class: "hide-for-small-only" do %> - <%= image_tag('logo_header.png', class: 'hide-for-small-only float-left', size: '80x80', alt: t("layouts.header.logo")) %> + <%= image_tag(image_path_for('logo_header.png'), class: 'hide-for-small-only float-left', size: '80x80', alt: t("layouts.header.logo")) %> <%= setting['org_name'] %>  | <%= t("management.dashboard.index.title") %> <% end %> diff --git a/app/views/shared/_social_media_meta_tags.html.erb b/app/views/shared/_social_media_meta_tags.html.erb index 50a2efec9..c0e6a5e8a 100644 --- a/app/views/shared/_social_media_meta_tags.html.erb +++ b/app/views/shared/_social_media_meta_tags.html.erb @@ -3,7 +3,7 @@ - + <% if setting['url'] %> @@ -14,7 +14,7 @@ <% end %> - + diff --git a/app/views/welcome/index.html.erb b/app/views/welcome/index.html.erb index 32124a950..1eb6cf38c 100644 --- a/app/views/welcome/index.html.erb +++ b/app/views/welcome/index.html.erb @@ -12,7 +12,7 @@
    - <%= image_tag("icon_home.png", size: "330x240", alt:"") %> + <%= image_tag(image_path_for("icon_home.png"), size: "330x240", alt:"") %>
    diff --git a/config/locales/activerecord.en.yml b/config/locales/activerecord.en.yml index e8354b88e..bd18422ae 100644 --- a/config/locales/activerecord.en.yml +++ b/config/locales/activerecord.en.yml @@ -43,6 +43,9 @@ en: site_customization/page: one: Custom page other: Custom pages + site_customization/image: + one: Custom image + other: Custom images attributes: budget: name: "Name" @@ -151,3 +154,8 @@ en: attributes: slug: slug_format: "must be letters, numbers, _ and -" + site_customization/image: + attributes: + image: + image_width: "Width must be %{required_width}px" + image_height: "Height must be %{required_height}px" diff --git a/config/locales/activerecord.es.yml b/config/locales/activerecord.es.yml index 32b26223b..f3397ef19 100644 --- a/config/locales/activerecord.es.yml +++ b/config/locales/activerecord.es.yml @@ -43,6 +43,9 @@ es: site_customization/page: one: Página other: Páginas + site_customization/image: + one: Imagen + other: Imágenes attributes: budget: name: "Nombre" @@ -146,3 +149,8 @@ es: attributes: slug: slug_format: "deber ser letras, números, _ y -" + site_customization/image: + attributes: + image: + image_width: "Debe tener %{required_width}px de ancho" + image_height: "Debe tener %{required_height}px de alto" diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index be2f9280e..5f84f69d3 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -209,6 +209,7 @@ en: signature_sheets: Signature Sheets site_customization: pages: Custom Pages + images: Custom Images moderators: index: title: Moderators @@ -478,12 +479,23 @@ en: sms_code_not_confirmed: Has not confirmed the sms code title: Incomplete verifications site_customization: + images: + index: + title: Custom images + update: Update + delete: Delete + update: + notice: Image updated successfully + error: Image couldn't be updated + destroy: + notice: Image deleted successfully + error: Image couldn't be deleted pages: create: - notice: 'Page created successfully.' + notice: Page created successfully error: Process couldn't be created update: - notice: 'Page updated successfully.' + notice: Page updated successfully error: Page couldn't be updated destroy: notice: Page deleted successfully diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index 7b14bf90a..f4c834e34 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -208,7 +208,8 @@ es: stats: Estadísticas signature_sheets: Hojas de firmas site_customization: - pages: Páginas + pages: Personalizar páginas + images: Personalizar imágenes moderators: index: title: Moderadores @@ -478,12 +479,23 @@ es: sms_code_not_confirmed: No ha introducido su código de seguridad title: Verificaciones incompletas site_customization: + images: + index: + title: Personalizar imágenes + update: Actualizar + delete: Borrar + update: + notice: Imagen actualizada correctamente + error: No se ha podido actualizar la imagen + destroy: + notice: Imagen borrada correctamente + error: No se ha podido borrar la imagen pages: create: - notice: 'Página creada correctamente.' + notice: Página creada correctamente error: No se ha podido crear la página update: - notice: 'Página actualizada correctamente.s' + notice: Página actualizada correctamente error: No se ha podido actualizar la página destroy: notice: Página eliminada correctamente diff --git a/config/routes.rb b/config/routes.rb index af9ac8a08..51d2a47da 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -225,6 +225,7 @@ Rails.application.routes.draw do namespace :site_customization do resources :pages, except: [:show] + resources :images, only: [:index, :update, :destroy] end end diff --git a/db/migrate/20170322145702_create_site_customization_images.rb b/db/migrate/20170322145702_create_site_customization_images.rb new file mode 100644 index 000000000..4f980b566 --- /dev/null +++ b/db/migrate/20170322145702_create_site_customization_images.rb @@ -0,0 +1,11 @@ +class CreateSiteCustomizationImages < ActiveRecord::Migration + def change + create_table :site_customization_images do |t| + t.string :name, null: false + t.attachment :image + t.timestamps null: false + end + + add_index :site_customization_images, :name, unique: true + end +end diff --git a/db/schema.rb b/db/schema.rb index 0b38a4196..938fbb9ec 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: 20170316174351) do +ActiveRecord::Schema.define(version: 20170322145702) do # These are extensions that must be enabled in order to support this database enable_extension "plpgsql" @@ -439,6 +439,18 @@ ActiveRecord::Schema.define(version: 20170316174351) do t.datetime "updated_at" end + create_table "site_customization_images", force: :cascade do |t| + t.string "name", null: false + t.string "image_file_name" + t.string "image_content_type" + t.integer "image_file_size" + t.datetime "image_updated_at" + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + end + + add_index "site_customization_images", ["name"], name: "index_site_customization_images_on_name", unique: true, using: :btree + create_table "site_customization_pages", force: :cascade do |t| t.string "slug", null: false t.string "title", null: false diff --git a/spec/features/admin/site_customization/images_spec.rb b/spec/features/admin/site_customization/images_spec.rb new file mode 100644 index 000000000..094ac19bf --- /dev/null +++ b/spec/features/admin/site_customization/images_spec.rb @@ -0,0 +1,62 @@ +require 'rails_helper' + +feature "Admin custom images" do + + background do + admin = create(:administrator) + login_as(admin.user) + end + + scenario "Upload valid image" do + visit admin_root_path + + within("#side_menu") do + click_link "Custom Images" + end + + within("tr.logo_header") do + attach_file "site_customization_image_image", "spec/fixtures/files/logo_header.png" + click_button "Update" + end + + expect(page).to have_css("tr.logo_header img[src*='logo_header.png']") + expect(page).to have_css("img[src*='logo_header.png']", count: 2) # one in the admin form an one in the page header + end + + scenario "Upload invalid image" do + visit admin_root_path + + within("#side_menu") do + click_link "Custom Images" + end + + within("tr.icon_home") do + attach_file "site_customization_image_image", "spec/fixtures/files/logo_header.png" + click_button "Update" + end + + expect(page).to have_content("Width must be 330px") + expect(page).to have_content("Height must be 240px") + end + + scenario "Delete image" do + visit admin_root_path + + within("#side_menu") do + click_link "Custom Images" + end + + within("tr.social-media-icon") do + attach_file "site_customization_image_image", "spec/fixtures/files/social-media-icon.png" + click_button "Update" + end + + expect(page).to have_css("img[src*='social-media-icon.png']") + + within("tr.social-media-icon") do + click_link "Delete" + end + + expect(page).to_not have_css("img[src*='social-media-icon.png']") + end +end diff --git a/spec/features/admin/site_customization/pages_spec.rb b/spec/features/admin/site_customization/pages_spec.rb index 20b817f50..5d03638d8 100644 --- a/spec/features/admin/site_customization/pages_spec.rb +++ b/spec/features/admin/site_customization/pages_spec.rb @@ -39,7 +39,7 @@ feature "Admin custom pages" do context "Update" do scenario "Valid custom page" do - custom_page = create(:site_customization_page, title: "An example custom page") + create(:site_customization_page, title: "An example custom page") visit admin_root_path within("#side_menu") do @@ -58,7 +58,7 @@ feature "Admin custom pages" do end end - scenario "Index" do + scenario "Delete" do custom_page = create(:site_customization_page, title: "An example custom page") visit edit_admin_site_customization_page_path(custom_page) diff --git a/spec/fixtures/files/logo_header.png b/spec/fixtures/files/logo_header.png new file mode 100644 index 0000000000000000000000000000000000000000..5f53555744121150dfe598df06fe86f37079d3d7 GIT binary patch literal 463 zcmeAS@N?(olHy`uVBq!ia0vp^0U*r51|<6gKdl8)Y)RhkE)4%caKYZ?lYt_f1s;*b z3=G`DAk4@xYmNj^kiEpy*OmPtvzP#z^keqBd<+bXF`h1tAr-gY-nlKyo5Xf?>f2fHB@6Y;-h8rto}ik%bkW2_PtCh0zDlq#FmWg}usARzr=6AEkbnG& z@X^18@hcp56+F<32|jnY$9Qr@bbm^<^id?ru2F59`e}y~bP0l+XkKoT#qZ literal 0 HcmV?d00001 diff --git a/spec/fixtures/files/social-media-icon.png b/spec/fixtures/files/social-media-icon.png new file mode 100644 index 0000000000000000000000000000000000000000..fcd00e212f4902b2cf737405a3b55024703ecfcf GIT binary patch literal 3353 zcmZ{n2T&7Ax5tyvq)A7*6zRPPD1@K{LlL;NP^EW}jzB`ol`36&Nsta2iYUZL3m_mD z5T%G9hF}l{6@-MMpuF5~=6&t?&d%ALIsZAkb7r>uHtP>d7(0s)3jhFMH#LFU(8lL~ z`x!=B-{#nkp$&{)<}fJW^zU}BzqyDOVGcKOiUI&wdH!}Fpt4$k7G#PxwJ>H{qvPii z<3P|Kivj>_O{UN*c5%yJ(ZM;@_M#azfw4GWdA^);AY~VrB|)#aOKOXJ(XNHH zFIkc(f@1mf9n4|RSp+VylP5h zE2Ckfvq%+^s<<&0b9_VWK%8uh`UQ#C`TTe2N^u%UP;<*WuI5L1*{EYTW<-uu+he0% zA_v&_QLt87cnuUz3G@K!F8S6!;?`xEvb#U(Q1&!T?;-sDC?b2+ogTZRv5|Fz?q}|^ zYvs>>>;jh}mixj7WkSR)6{)#|*pwK8Qg~l>a61T2*8xffif!#?yKI4lQEz)Q@c=Av z10{<>qRL=x>W`QNxs2RY7PJ8nh9tJ@zTv%>NMfXRvu@qF2d`Ahg3{y$>6I-V3*B$TjXUYlVC1mE#_zz0tf*OoLMO^)XiMPs}sHT zI@@fN#oUxiwGmCZ1bU5KM!Q<8>XhOe(!I=d1qsY3$IDxo_rs8n*)KEd<@35d7q)%EHO6<+*9%2iJdudxzIpUI(+<1w17}ztpM#4$92C``O7D?F3;mRwprU z|5a4=r$@R%>Q-Z72UqVg>UTja6bgKOUaaQw-Sh(BV`dMp%j6uN_3)3xG^7z!?`$M^ zYpp+E{KIXcT-M8}zY6vUBU|Ja_G2Y#*BpY&A82_w{Nxe)19;!YSJrWkRYu+L_x$wsf1|pYaCYtBGAG z$o22v#C%3^aBT=fQEVk8sXyPdIbAT7GB9@}Hyr*UZuC*kGlJx5>#NLWD#DqL_*ll7 zDdmDFK&ct&2CnlBcTs|E5QRw&V;jfV+aMc6m8jtQ^4(A1^i(ON@kL-Gzi6pp6%bwogZj>X zk**e>4QeI{6AlDceN+3XX)-{0euleFL319$YYl~ujf5GkcikkFL|27u2fedT-u0*Q zSP!r!Bxc@bW$_VgvTs(f*%O$F>w4aPwA@WAt%&ZrJCPoPwacElfatwiG}tmeBIG7t z7Q~d2Z@l_=NGn)vJpzx^R0Sl1w*7W<4P&|>DG2$nLj8qx`c8%;x46`3f0(#VdO$O$$euerR`tB+VXRkrJJng)5vAJ#%4=~%h zYe2n0+Rb*n2fq}lS}~T{tgQx2#Z%i^rX*=ngwHJLjV)3bHvNw%#v7(ANaKew= z7VAFBQU55EMH#&lAOgo$HX{=(5P59hWrn?Hx5azMyQFQq0*85mnvo_;j9i+1gHyjO zNfFMf<2a^?LW$MlyLD9BLK}x)=*~)a3>L46UY%kmf_|0sh$Q1VzHVF^6-t$`G7mn> zrF{*|pg&!auPHEEJ`)JMp3_mBQ1d~jx8=z?J%M^af^e%OQ|wKu_>|6k((!C_=^aiSRYtT(s}q&YYi$i6YSQEYPJA zmLBK&Cc{#l@p>nWq=;Ce^4ccODf)Cm@RPjdYAiAP8ysr&QYp`}tiPerD}%YYFNCf~ z>wAN1*wXZ8{pSzOx}TJE&X74?LH)mOZg~5;RoT?`u3hllYsc^LBQhUeA(QSPZS-O7 z97)gL>YGr0ZIdHv#uJ1$Vp>H83OL75qM zH?svIXXb_%`Z!CI^#OfsuIJg0x3s5k-t}j0&I!p6G0FC;V zuMQh4kWg0 zgl(Z;yqPbK=)lcq?X-C%nHjYkBG%%x-cV9~*KwQ&F^eg%`nVTakl2PSDLNx!d!Q9& zu2*^>iD!+zw3S~S(k9^`-cMC{L>QcGTux@rrnZAr7=F>67>I>}MO{9SMJu->Zf0~bhwjJw%?j>MW$b&J-ZIvFNU7d9|bo$_YJ-~6ry6aw*Zf}q{7*)uQSona_aDK3u<~#8|6u9=)kVn^X5Wyl7iySDm;CedvYlql z?_2VFCEKW7ScDMxHxv#nRRmkL(4K>_n5};yy}Fqfk6`!H@&#w5vhwG0o{79%zqbkb bQzobvL?qkdav$vz128qVgtlMx`15}Nuhbo& literal 0 HcmV?d00001 From ae3690ab5f43e7b9832e8d5fd08b4054e4883bdd Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Wed, 5 Apr 2017 13:26:57 +0200 Subject: [PATCH 07/13] Validate presence of page slug --- app/models/site_customization/page.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/app/models/site_customization/page.rb b/app/models/site_customization/page.rb index ea3003465..c2a9b1467 100644 --- a/app/models/site_customization/page.rb +++ b/app/models/site_customization/page.rb @@ -1,8 +1,9 @@ class SiteCustomization::Page < ActiveRecord::Base VALID_STATUSES = %w(draft published) - validates :slug, uniqueness: { case_sensitive: false }, - format: { with: /\A[0-9a-zA-Z\-_]*\Z/, message: :slug_format } + validates :slug, presence: true, + uniqueness: { case_sensitive: false }, + format: { with: /\A[0-9a-zA-Z\-_]*\Z/, message: :slug_format } validates :title, presence: true validates :status, presence: true, inclusion: { in: VALID_STATUSES } From c1de2dced4c26447002badc1b955747b67a07afd Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Fri, 24 Mar 2017 17:12:33 +0100 Subject: [PATCH 08/13] Custom content blocks for top_links and footer --- .gitignore | 3 +- .../content_blocks_controller.rb | 40 +++++++ app/helpers/application_helper.rb | 4 + app/models/abilities/administrator.rb | 1 + .../site_customization/content_block.rb | 11 ++ app/views/admin/_menu.html.erb | 6 + .../content_blocks/_form.html.erb | 34 ++++++ .../content_blocks/edit.html.erb | 15 +++ .../content_blocks/index.html.erb | 29 +++++ .../content_blocks/new.html.erb | 14 +++ app/views/layouts/_footer.html.erb | 6 +- app/views/shared/_top_links.html.erb | 14 ++- config/locales/activerecord.en.yml | 10 ++ config/locales/activerecord.es.yml | 10 ++ config/locales/admin.en.yml | 28 ++++- config/locales/admin.es.yml | 26 +++++ config/routes.rb | 1 + ...reate_site_customization_content_blocks.rb | 13 +++ db/schema.rb | 12 +- db/seeds.rb | 2 + spec/factories.rb | 6 + .../site_customization/content_blocks_spec.rb | 107 ++++++++++++++++++ .../site_customization/content_blocks_spec.rb | 33 ++++++ .../site_customization/content_block_spec.rb | 20 ++++ 24 files changed, 435 insertions(+), 10 deletions(-) create mode 100644 app/controllers/admin/site_customization/content_blocks_controller.rb create mode 100644 app/models/site_customization/content_block.rb create mode 100644 app/views/admin/site_customization/content_blocks/_form.html.erb create mode 100644 app/views/admin/site_customization/content_blocks/edit.html.erb create mode 100644 app/views/admin/site_customization/content_blocks/index.html.erb create mode 100644 app/views/admin/site_customization/content_blocks/new.html.erb create mode 100644 db/migrate/20170324101716_create_site_customization_content_blocks.rb create mode 100644 spec/features/admin/site_customization/content_blocks_spec.rb create mode 100644 spec/features/site_customization/content_blocks_spec.rb create mode 100644 spec/models/site_customization/content_block_spec.rb 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 @@
    -
    +

    <%= link_to t("layouts.header.open_gov", open: "#{t('layouts.header.open')}").html_safe %> @@ -25,7 +25,7 @@

    - <%= 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") %>

    <%= t("layouts.footer.transparency_text") %>

    @@ -96,4 +96,6 @@

    + + <%= raw content_block("footer", I18n.locale) %>
    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 From d5669fbbaecefe065b9674a3696a46019577587d Mon Sep 17 00:00:00 2001 From: Fernando Blat Date: Thu, 6 Apr 2017 08:11:03 +0200 Subject: [PATCH 09/13] Add settings translation --- config/locales/settings.en.yml | 2 ++ config/locales/settings.es.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/config/locales/settings.en.yml b/config/locales/settings.en.yml index 7e126bc35..72aa390db 100755 --- a/config/locales/settings.en.yml +++ b/config/locales/settings.en.yml @@ -20,6 +20,8 @@ en: facebook_handle: "Facebook handle" youtube_handle: "Youtube handle" blog_url: "Blog URL" + transparency_url: "Transparency URL" + opendata_url: "Open Data URL" url: "Main URL" org_name: "Organization" place_name: "Place" diff --git a/config/locales/settings.es.yml b/config/locales/settings.es.yml index 27224d90b..afb48d799 100644 --- a/config/locales/settings.es.yml +++ b/config/locales/settings.es.yml @@ -20,6 +20,8 @@ es: facebook_handle: "Identificador de Facebook" youtube_handle: "Usuario de Youtube" blog_url: "URL del blog" + transparency_url: "URL de transparencia" + opendata_url: "URL de open data" url: "URL general de la web" org_name: "Nombre de la organización" place_name: "Nombre del lugar" From 3a275ea8506a744f74aef6d98f58fcbbc8a9f37e Mon Sep 17 00:00:00 2001 From: Fernando Blat Date: Thu, 6 Apr 2017 08:20:24 +0200 Subject: [PATCH 10/13] Use open data setting in footer links --- app/views/layouts/_footer.html.erb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb index 1e5c3dfa5..55ff90bf3 100644 --- a/app/views/layouts/_footer.html.erb +++ b/app/views/layouts/_footer.html.erb @@ -32,7 +32,7 @@

    - <%= link_to t("layouts.footer.open_data_title"), "/opendata" %> + <%= link_to t("layouts.footer.open_data_title"), setting['opendata_url'].presence || t("layouts.header.external_link_opendata_url") %>

    <%= t("layouts.footer.open_data_text") %>

    From e126a2ded0ad275e47063c3c5bb98cbfc89b8351 Mon Sep 17 00:00:00 2001 From: Fernando Blat Date: Thu, 6 Apr 2017 08:37:46 +0200 Subject: [PATCH 11/13] Add information about content blocks --- .../content_blocks/_form.html.erb | 15 ++++++++++++++- config/locales/admin.en.yml | 5 +++++ config/locales/admin.es.yml | 5 +++++ 3 files changed, 24 insertions(+), 1 deletion(-) diff --git a/app/views/admin/site_customization/content_blocks/_form.html.erb b/app/views/admin/site_customization/content_blocks/_form.html.erb index 9ca4eb36a..b5a692d87 100644 --- a/app/views/admin/site_customization/content_blocks/_form.html.erb +++ b/app/views/admin/site_customization/content_blocks/_form.html.erb @@ -15,7 +15,6 @@ <% end %> -
    <%= f.label :name %> <%= f.select :name, SiteCustomization::ContentBlock::VALID_BLOCKS, label: false %> @@ -32,3 +31,17 @@
    <% end %> + +

    <%= t('.content_blocks_information') %>

    + +

    <%= t('.content_block_about') %>

    + +

    <%= t('.content_block_top_links_html') %>

    +
    +<li><a href="http://site1.com">Site 1</a></li>
    +<li><a href="http://site2.com">Site 2</a></li>
    +<li><a href="http://site3.com">Site 3</a></li>
    +
    +
    + +

    <%= t('.content_block_footer_html') %>

    diff --git a/config/locales/admin.en.yml b/config/locales/admin.en.yml index 12911c410..4ad60f2a4 100755 --- a/config/locales/admin.en.yml +++ b/config/locales/admin.en.yml @@ -481,6 +481,11 @@ en: title: Incomplete verifications site_customization: content_blocks: + form: + content_blocks_information: Information about content blocks + content_block_about: You can create HTML content blocks to be inserted in the header or the footer of your Consul. + content_block_top_links_html: "Header blocks (top_links) are blocks of links that must have this format:" + content_block_footer_html: "Footer blocks can have any format and can be used to insert Javascript, CSS or custom HTML." create: notice: Content block created successfully error: Content block couldn't be created diff --git a/config/locales/admin.es.yml b/config/locales/admin.es.yml index feb72e24c..96ff667df 100644 --- a/config/locales/admin.es.yml +++ b/config/locales/admin.es.yml @@ -481,6 +481,11 @@ es: title: Verificaciones incompletas site_customization: content_blocks: + form: + content_blocks_information: Información sobre los bloques de texto + content_block_about: Puedes crear bloques de HTML que se incrustarán en la cabecera o el pie de tu Cónsul. + content_block_top_links_html: "Los bloques de la cabecera (top_links) son bloques de enlaces que deben crearse con este formato:" + content_block_footer_html: "Los bloques del pie (footer) pueden tener cualquier formato y se pueden utilizar para guardar huellas Javascript, contenido CSS o contenido HTML personalizado." create: notice: Bloque creado correctamente error: No se ha podido crear el bloque From b0b39d9f8a93c80425598746c691aac2e24a86ae Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Thu, 6 Apr 2017 16:05:09 +0200 Subject: [PATCH 12/13] Remove sandbox Revert "Implement Sandbox" This reverts commit e806a39820c2920d18b80dc560d05db36ecb6ede. --- app/controllers/sandbox_controller.rb | 45 --------------------------- app/views/sandbox/index.html.erb | 13 -------- config/routes.rb | 5 --- 3 files changed, 63 deletions(-) delete mode 100644 app/controllers/sandbox_controller.rb delete mode 100644 app/views/sandbox/index.html.erb diff --git a/app/controllers/sandbox_controller.rb b/app/controllers/sandbox_controller.rb deleted file mode 100644 index 12b5dd91e..000000000 --- a/app/controllers/sandbox_controller.rb +++ /dev/null @@ -1,45 +0,0 @@ -class SandboxController < ApplicationController - skip_authorization_check - - layout :set_layout - - helper_method(:namespace) - - def index - @templates = Dir.glob(Rails.root.join('app/views/sandbox/*.html.erb').to_s).map do |filename| - filename = File.basename(filename, File.extname(filename)) - filename unless filename.starts_with?('_') || filename == 'index.html' - end.compact - end - - def show - if params[:template].index('.') # CVE-2014-0130 - render :action => "index" - elsif lookup_context.exists?("sandbox/#{params[:template]}") - if params[:template] == "index" - render :action => "index" - else - render "sandbox/#{params[:template]}" - end - - elsif lookup_context.exists?("sandbox/#{params[:template]}/index") - render "sandbox/#{params[:template]}/index" - else - render :action => "index" - end - end - - private - - def set_layout - if params[:template] && params[:template].split("_").first == "admin" - "admin" - else - "application" - end - end - - def namespace - "admin" - end -end diff --git a/app/views/sandbox/index.html.erb b/app/views/sandbox/index.html.erb deleted file mode 100644 index 9d6303698..000000000 --- a/app/views/sandbox/index.html.erb +++ /dev/null @@ -1,13 +0,0 @@ -
    -
    -
    -

    Welcome to sandbox

    - -
      - <% @templates.each do |template| %> -
    • <%= link_to template, "/sandbox/" + template %>
    • - <% end %> -
    -
    -
    -
    diff --git a/config/routes.rb b/config/routes.rb index 2088c48da..63b04458b 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,10 +1,5 @@ Rails.application.routes.draw do - if Rails.env.development? || Rails.env.staging? - get '/sandbox' => 'sandbox#index' - get '/sandbox/*template' => 'sandbox#show' - end - devise_for :users, controllers: { registrations: 'users/registrations', sessions: 'users/sessions', From 613f5521a2d40db269bf42f37cec3a9058299ee2 Mon Sep 17 00:00:00 2001 From: Amaia Castro Date: Thu, 6 Apr 2017 17:24:09 +0200 Subject: [PATCH 13/13] Put footer block inside row div --- app/views/layouts/_footer.html.erb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/views/layouts/_footer.html.erb b/app/views/layouts/_footer.html.erb index 55ff90bf3..0bce1cd67 100644 --- a/app/views/layouts/_footer.html.erb +++ b/app/views/layouts/_footer.html.erb @@ -97,5 +97,7 @@
    - <%= raw content_block("footer", I18n.locale) %> +
    + <%= raw content_block("footer", I18n.locale) %> +