Make budget phases translatable

This commit is contained in:
Julian Herrero
2019-01-20 15:32:14 +01:00
parent f38c4e3a0c
commit 90d0a6e416
10 changed files with 110 additions and 39 deletions

View File

@@ -1,4 +1,5 @@
class Admin::BudgetPhasesController < Admin::BaseController class Admin::BudgetPhasesController < Admin::BaseController
include Translatable
before_action :load_phase, only: [:edit, :update] before_action :load_phase, only: [:edit, :update]
@@ -21,8 +22,8 @@ class Admin::BudgetPhasesController < Admin::BaseController
end end
def budget_phase_params def budget_phase_params
valid_attributes = [:starts_at, :ends_at, :summary, :description, :enabled] valid_attributes = [:starts_at, :ends_at, :enabled]
params.require(:budget_phase).permit(*valid_attributes) params.require(:budget_phase).permit(*valid_attributes, translation_params(Budget::Phase))
end end
end end

View File

@@ -6,20 +6,22 @@ class Budget
SUMMARY_MAX_LENGTH = 1000 SUMMARY_MAX_LENGTH = 1000
DESCRIPTION_MAX_LENGTH = 2000 DESCRIPTION_MAX_LENGTH = 2000
translates :summary, touch: true
translates :description, touch: true
include Globalizable
belongs_to :budget belongs_to :budget
belongs_to :next_phase, class_name: 'Budget::Phase', foreign_key: :next_phase_id belongs_to :next_phase, class_name: 'Budget::Phase', foreign_key: :next_phase_id
has_one :prev_phase, class_name: 'Budget::Phase', foreign_key: :next_phase_id has_one :prev_phase, class_name: 'Budget::Phase', foreign_key: :next_phase_id
validates_translation :summary, length: { maximum: SUMMARY_MAX_LENGTH }
validates_translation :description, length: { maximum: DESCRIPTION_MAX_LENGTH }
validates :budget, presence: true validates :budget, presence: true
validates :kind, presence: true, uniqueness: { scope: :budget }, inclusion: { in: PHASE_KINDS } validates :kind, presence: true, uniqueness: { scope: :budget }, inclusion: { in: PHASE_KINDS }
validates :summary, length: { maximum: SUMMARY_MAX_LENGTH }
validates :description, length: { maximum: DESCRIPTION_MAX_LENGTH }
validate :invalid_dates_range? validate :invalid_dates_range?
validate :prev_phase_dates_valid? validate :prev_phase_dates_valid?
validate :next_phase_dates_valid? validate :next_phase_dates_valid?
before_validation :sanitize_description
after_save :adjust_date_ranges after_save :adjust_date_ranges
after_save :touch_budget after_save :touch_budget
@@ -87,8 +89,5 @@ class Budget
end end
end end
def sanitize_description
self.description = WYSIWYGSanitizer.new.sanitize(description)
end
end end
end end

View File

@@ -0,0 +1,9 @@
class Budget::Phase::Translation < Globalize::ActiveRecord::Translation
before_validation :sanitize_description
private
def sanitize_description
self.description = WYSIWYGSanitizer.new.sanitize(description)
end
end

View File

@@ -1,4 +1,8 @@
<%= form_for [:admin, @phase.budget, @phase] do |f| %> <%= render "admin/shared/globalize_locales", resource: @phase %>
<%= translatable_form_for [:admin, @phase.budget, @phase] do |f| %>
<%= render 'shared/errors', resource: @phase %>
<div class="small-12 medium-6 column"> <div class="small-12 medium-6 column">
<%= f.label :starts_at, t("admin.budget_phases.edit.start_date") %> <%= f.label :starts_at, t("admin.budget_phases.edit.start_date") %>
@@ -18,31 +22,33 @@
</div> </div>
<div class="small-12 column"> <div class="small-12 column">
<%= f.translatable_fields do |translations_form| %>
<%= f.label :description, t("admin.budget_phases.edit.description") %> <%= f.label :description, t("admin.budget_phases.edit.description") %>
<span class="help-text" id="phase-description-help-text"> <span class="help-text" id="phase-description-help-text">
<%= t("admin.budget_phases.edit.description_help_text") %> <%= t("admin.budget_phases.edit.description_help_text") %>
</span> </span>
<%= f.cktext_area :description, <div class="ckeditor">
<%= translations_form.cktext_area :description,
maxlength: Budget::Phase::DESCRIPTION_MAX_LENGTH, maxlength: Budget::Phase::DESCRIPTION_MAX_LENGTH,
ckeditor: { language: I18n.locale },
label: false %> label: false %>
</div> </div>
<div class="small-12 column margin-top">
<%= f.label :summary, t("admin.budget_phases.edit.summary") %> <%= f.label :summary, t("admin.budget_phases.edit.summary") %>
<span class="help-text" id="phase-summary-help-text"> <span class="help-text" id="phase-summary-help-text">
<%= t("admin.budget_phases.edit.summary_help_text") %> <%= t("admin.budget_phases.edit.summary_help_text") %>
</span> </span>
<%= f.cktext_area :summary, <div class="ckeditor">
<%= translations_form.cktext_area :summary,
maxlength: Budget::Phase::SUMMARY_MAX_LENGTH, maxlength: Budget::Phase::SUMMARY_MAX_LENGTH,
ckeditor: { language: I18n.locale },
label: false%> label: false%>
</div> </div>
<% end %>
</div>
<div class="small-12 column margin-top"> <div class="small-12 column margin-top">
<%= f.check_box :enabled, label: t("admin.budget_phases.edit.enabled") %> <%= f.check_box :enabled, label: t("admin.budget_phases.edit.enabled") %>

View File

@@ -5,7 +5,7 @@
module ActionDispatch::Routing::UrlFor module ActionDispatch::Routing::UrlFor
def resource_hierarchy_for(resource) def resource_hierarchy_for(resource)
case resource.class.name case resource.class.name
when "Budget::Investment" when "Budget::Investment", "Budget::Phase"
[resource.budget, resource] [resource.budget, resource]
when "Milestone" when "Milestone"
[*resource_hierarchy_for(resource.milestoneable), resource] [*resource_hierarchy_for(resource.milestoneable), resource]

View File

@@ -39,6 +39,18 @@ section "Creating Budgets" do
phase: "accepting" phase: "accepting"
) )
Budget.find_each do |budget|
budget.phases.each do |phase|
random_locales.map do |locale|
Globalize.with_locale(locale) do
phase.description = "Description for locale #{locale}"
phase.summary = "Summary for locale #{locale}"
phase.save!
end
end
end
end
Budget.all.each do |budget| Budget.all.each do |budget|
city_group = budget.groups.create!(name: I18n.t('seeds.budgets.groups.all_city')) city_group = budget.groups.create!(name: I18n.t('seeds.budgets.groups.all_city'))
city_group.headings.create!(name: I18n.t('seeds.budgets.groups.all_city'), city_group.headings.create!(name: I18n.t('seeds.budgets.groups.all_city'),

View File

@@ -0,0 +1,17 @@
class AddBudgetPhaseTranslations < ActiveRecord::Migration
def self.up
Budget::Phase.create_translation_table!(
{
description: :text,
summary: :text
},
{ migrate_data: true }
)
end
def self.down
Budget::Phase.drop_translation_table!
end
end

View File

@@ -242,6 +242,18 @@ ActiveRecord::Schema.define(version: 20190205131722) do
add_index "budget_investments", ["heading_id"], name: "index_budget_investments_on_heading_id", using: :btree add_index "budget_investments", ["heading_id"], name: "index_budget_investments_on_heading_id", using: :btree
add_index "budget_investments", ["tsv"], name: "index_budget_investments_on_tsv", using: :gin add_index "budget_investments", ["tsv"], name: "index_budget_investments_on_tsv", using: :gin
create_table "budget_phase_translations", force: :cascade do |t|
t.integer "budget_phase_id", null: false
t.string "locale", null: false
t.datetime "created_at", null: false
t.datetime "updated_at", null: false
t.text "description"
t.text "summary"
end
add_index "budget_phase_translations", ["budget_phase_id"], name: "index_budget_phase_translations_on_budget_phase_id", using: :btree
add_index "budget_phase_translations", ["locale"], name: "index_budget_phase_translations_on_locale", using: :btree
create_table "budget_phases", force: :cascade do |t| create_table "budget_phases", force: :cascade do |t|
t.integer "budget_id" t.integer "budget_id"
t.integer "next_phase_id" t.integer "next_phase_id"

View File

@@ -10,13 +10,19 @@ feature 'Admin budget phases' do
login_as(admin.user) login_as(admin.user)
end end
scenario 'Update phase' do it_behaves_like "translatable",
"budget_phase",
"edit_admin_budget_budget_phase_path",
[],
{ "description" => :ckeditor, "summary" => :ckeditor }
scenario "Update phase", :js do
visit edit_admin_budget_budget_phase_path(budget, budget.current_phase) visit edit_admin_budget_budget_phase_path(budget, budget.current_phase)
fill_in 'start_date', with: Date.current + 1.days fill_in 'start_date', with: Date.current + 1.days
fill_in 'end_date', with: Date.current + 12.days fill_in 'end_date', with: Date.current + 12.days
fill_in 'budget_phase_summary', with: 'This is the summary of the phase.' fill_in_translatable_ckeditor "summary", :en, with: "New summary of the phase."
fill_in 'budget_phase_description', with: 'This is the description of the phase.' fill_in_translatable_ckeditor "description", :en, with: "New description of the phase."
uncheck 'budget_phase_enabled' uncheck 'budget_phase_enabled'
click_button 'Save changes' click_button 'Save changes'
@@ -25,8 +31,8 @@ feature 'Admin budget phases' do
expect(budget.current_phase.starts_at.to_date).to eq((Date.current + 1.days).to_date) expect(budget.current_phase.starts_at.to_date).to eq((Date.current + 1.days).to_date)
expect(budget.current_phase.ends_at.to_date).to eq((Date.current + 12.days).to_date) expect(budget.current_phase.ends_at.to_date).to eq((Date.current + 12.days).to_date)
expect(budget.current_phase.summary).to eq('This is the summary of the phase.') expect(budget.current_phase.summary).to include("New summary of the phase.")
expect(budget.current_phase.description).to eq('This is the description of the phase.') expect(budget.current_phase.description).to include("New description of the phase.")
expect(budget.current_phase.enabled).to be(false) expect(budget.current_phase.enabled).to be(false)
end end
end end

View File

@@ -32,7 +32,16 @@ shared_examples "translatable" do |factory_name, path_name, input_fields, textar
fields - optional_fields fields - optional_fields
end end
let(:translatable) { create(factory_name, attributes) } let(:translatable) do
if factory_name == "budget_phase"
budget = create(:budget)
budget.phases.first.update attributes
budget.phases.first
else
create(factory_name, attributes)
end
end
let(:path) { send(path_name, *resource_hierarchy_for(translatable)) } let(:path) { send(path_name, *resource_hierarchy_for(translatable)) }
before { login_as(create(:administrator).user) } before { login_as(create(:administrator).user) }