Extract model to handle locales settings

This way we can simplify the view, particularly the form. However, we're
still adding some complexity to the form so inputs are inside labels and
so the collection is easier to style with CSS.
This commit is contained in:
Javi Martín
2024-04-10 03:38:00 +02:00
parent 2596b4e78b
commit 0c59c2dfb4
15 changed files with 99 additions and 47 deletions

View File

@@ -7,6 +7,10 @@
width: auto; width: auto;
} }
.help-text {
display: block;
}
> select + fieldset, > select + fieldset,
> fieldset + fieldset { > fieldset + fieldset {
margin-top: $line-height / 2; margin-top: $line-height / 2;

View File

@@ -1,37 +1,36 @@
<%= form_tag admin_locales_path, method: :patch, class: "locales-form" do %> <%= form_for locales_settings, url: admin_locales_path, html: { class: "locales-form" } do |f| %>
<% if many_available_locales? %> <% if many_available_locales? %>
<%= label_tag "default_locale", t("admin.locales.default") %> <%= f.select :default, locales_options, hint: sanitize(t("admin.locales.default_help_text")) %>
<p class="help-text"><%= sanitize(t("admin.locales.default_help_text")) %></p>
<%= select_tag "default_locale", locales_options %>
<% else %> <% else %>
<fieldset> <fieldset>
<legend><%= t("admin.locales.default") %></legend> <legend><%= attribute_name(:default) %></legend>
<p class="help-text"><%= sanitize(t("admin.locales.default_help_text")) %></p> <p class="help-text"><%= sanitize(t("admin.locales.default_help_text")) %></p>
<div class="collection-radio-buttons"> <div class="collection-radio-buttons">
<% available_locales.each do |locale| %> <%= f.collection_radio_buttons(
<%= label_tag "default_locale_#{locale}" do %> :default,
<%= radio_button_tag "default_locale", locale, locale == default %> available_locales,
<%= name_for_locale(locale) %> :to_sym,
<% end %> ->(locale) { name_for_locale(locale) }
) do |b| %>
<%= b.label { b.radio_button + b.text } %>
<% end %> <% end %>
</div> </div>
</fieldset> </fieldset>
<% end %> <% end %>
<fieldset> <fieldset>
<legend><%= t("admin.locales.enabled") %></legend> <legend><%= attribute_name(:enabled) %></legend>
<p class="help-text"><%= t("admin.locales.enabled_help_text") %></p> <p class="help-text"><%= t("admin.locales.enabled_help_text") %></p>
<div class="collection-check-boxes"> <div class="collection-check-boxes">
<% available_locales.each do |locale| %> <%= f.collection_check_boxes(
<%= label_tag "enabled_locales_#{locale}" do %> :enabled,
<%= check_box_tag "enabled_locales[]", available_locales,
locale, :to_sym,
enabled_locales.include?(locale), ->(locale) { name_for_locale(locale) }
id: "enabled_locales_#{locale}" %> ) do |b| %>
<%= name_for_locale(locale) %> <%= b.label { b.check_box + b.text } %>
<% end %>
<% end %> <% end %>
</div> </div>
</fieldset> </fieldset>

View File

@@ -1,10 +1,9 @@
class Admin::Locales::FormComponent < ApplicationComponent class Admin::Locales::FormComponent < ApplicationComponent
attr_reader :enabled_locales, :default attr_reader :locales_settings
use_helpers :name_for_locale use_helpers :name_for_locale
def initialize(enabled_locales, default:) def initialize(locales_settings)
@enabled_locales = enabled_locales @locales_settings = locales_settings
@default = default
end end
private private
@@ -18,13 +17,14 @@ class Admin::Locales::FormComponent < ApplicationComponent
end end
def locales_options def locales_options
options_for_select( available_locales.map { |locale| [name_for_locale(locale), locale] }
available_locales.map { |locale| [name_for_locale(locale), locale] },
default
)
end end
def select_field_threshold def select_field_threshold
10 10
end end
def attribute_name(...)
locales_settings.class.human_attribute_name(...)
end
end end

View File

@@ -1,4 +1,4 @@
<%= header %> <%= header %>
<% provide :main_class, "admin-locales-show" %> <% provide :main_class, "admin-locales-show" %>
<%= render Admin::Locales::FormComponent.new(locales, default: default) %> <%= render Admin::Locales::FormComponent.new(locales_settings) %>

View File

@@ -1,10 +1,9 @@
class Admin::Locales::ShowComponent < ApplicationComponent class Admin::Locales::ShowComponent < ApplicationComponent
include Header include Header
attr_reader :locales, :default attr_reader :locales_settings
def initialize(locales, default:) def initialize(locales_settings)
@locales = locales @locales_settings = locales_settings
@default = default
end end
def title def title

View File

@@ -1,15 +1,27 @@
class Admin::LocalesController < Admin::BaseController class Admin::LocalesController < Admin::BaseController
before_action :set_locales_settings
authorize_resource :locales_settings
def show def show
@enabled_locales = Setting.enabled_locales
@default_locale = Setting.default_locale
end end
def update def update
Setting.transaction do @locales_settings.update!(locales_settings_params)
Setting["locales.default"] = params["default_locale"]
Setting["locales.enabled"] = [params["default_locale"], *params["enabled_locales"]].join(" ")
end
redirect_to admin_locales_path, notice: t("admin.locales.update.notice") redirect_to admin_locales_path, notice: t("admin.locales.update.notice")
end end
private
def locales_settings_params
params.require(:setting_locales_settings).permit(allowed_params)
end
def allowed_params
[:default, enabled: []]
end
def set_locales_settings
@locales_settings = Setting::LocalesSettings.new
end
end end

View File

@@ -134,6 +134,8 @@ module Abilities
can [:deliver], Newsletter, hidden_at: nil can [:deliver], Newsletter, hidden_at: nil
can [:manage], Dashboard::AdministratorTask can [:manage], Dashboard::AdministratorTask
can :manage, Setting::LocalesSettings
can :manage, LocalCensusRecord can :manage, LocalCensusRecord
can [:create, :read], LocalCensusRecords::Import can [:create, :read], LocalCensusRecords::Import

View File

@@ -0,0 +1,23 @@
class Setting
class LocalesSettings
include ActiveModel::Model
include ActiveModel::Attributes
attribute :enabled, array: true, default: -> { Setting.enabled_locales }
attribute :default, default: -> { Setting.default_locale }
def persisted?
true
end
def update(attributes)
assign_attributes(attributes)
Setting.transaction do
Setting["locales.default"] = default
Setting["locales.enabled"] = [default, *enabled].join(" ")
end
end
alias_method :update!, :update
end
end

View File

@@ -1 +1 @@
<%= render Admin::Locales::ShowComponent.new(@enabled_locales, default: @default_locale) %> <%= render Admin::Locales::ShowComponent.new(@locales_settings) %>

View File

@@ -38,6 +38,9 @@ en:
year_of_birth: "Year born" year_of_birth: "Year born"
local_census_records/import: local_census_records/import:
file: File file: File
setting/locales_settings:
default: Default language
enabled: Enabled languages
errors: errors:
models: models:
local_census_records/import: local_census_records/import:

View File

@@ -711,9 +711,7 @@ en:
index: index:
title: Following title: Following
locales: locales:
default: Default language
default_help_text: "This is the default language of the application, and changing it will <strong>affect every user</strong> visiting the website for the first time." default_help_text: "This is the default language of the application, and changing it will <strong>affect every user</strong> visiting the website for the first time."
enabled: Enabled languages
enabled_help_text: The default language, selected above, will be included automatically. enabled_help_text: The default language, selected above, will be included automatically.
update: update:
notice: Languages updated successfully notice: Languages updated successfully

View File

@@ -38,6 +38,9 @@ es:
year_of_birth: "Año de nacimiento" year_of_birth: "Año de nacimiento"
local_census_records/import: local_census_records/import:
file: Archivo file: Archivo
setting/locales_settings:
default: Idioma por defecto
enabled: Idiomas habilitados
errors: errors:
models: models:
local_census_records/import: local_census_records/import:

View File

@@ -711,9 +711,7 @@ es:
index: index:
title: Seguimiento title: Seguimiento
locales: locales:
default: Idioma por defecto
default_help_text: "Cambiar el idioma por defecto <strong>afectará a todos los usuarios</strong> que visiten la página por primera vez." default_help_text: "Cambiar el idioma por defecto <strong>afectará a todos los usuarios</strong> que visiten la página por primera vez."
enabled: Idiomas habilitados
enabled_help_text: El idioma por defecto, seleccionado con anterioridad, se habilitará automáticamente. enabled_help_text: El idioma por defecto, seleccionado con anterioridad, se habilitará automáticamente.
update: update:
notice: Idiomas actualizados con éxito notice: Idiomas actualizados con éxito

View File

@@ -3,10 +3,8 @@ require "rails_helper"
describe Admin::Locales::FormComponent do describe Admin::Locales::FormComponent do
let(:default_locale) { :nl } let(:default_locale) { :nl }
let(:enabled_locales) { %i[en nl] } let(:enabled_locales) { %i[en nl] }
let(:locales_settings) { Setting::LocalesSettings.new(default: default_locale, enabled: enabled_locales) }
let(:component) do let(:component) { Admin::Locales::FormComponent.new(locales_settings) }
Admin::Locales::FormComponent.new(enabled_locales, default: default_locale)
end
describe "default language selector" do describe "default language selector" do
before { allow(I18n).to receive(:available_locales).and_return(%i[de en es nl]) } before { allow(I18n).to receive(:available_locales).and_return(%i[de en es nl]) }

View File

@@ -0,0 +1,13 @@
require "rails_helper"
describe Setting::LocalesSettings do
describe "#update!" do
it "saves the default locale in the enabled ones when nothing is enabled" do
Setting::LocalesSettings.new.update!(default: "es", enabled: %w[])
updated_locales_settings = Setting::LocalesSettings.new
expect(updated_locales_settings.default).to eq :es
expect(updated_locales_settings.enabled).to match_array [:es]
end
end
end