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;
}
.help-text {
display: block;
}
> select + fieldset,
> fieldset + fieldset {
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? %>
<%= label_tag "default_locale", t("admin.locales.default") %>
<p class="help-text"><%= sanitize(t("admin.locales.default_help_text")) %></p>
<%= select_tag "default_locale", locales_options %>
<%= f.select :default, locales_options, hint: sanitize(t("admin.locales.default_help_text")) %>
<% else %>
<fieldset>
<legend><%= t("admin.locales.default") %></legend>
<legend><%= attribute_name(:default) %></legend>
<p class="help-text"><%= sanitize(t("admin.locales.default_help_text")) %></p>
<div class="collection-radio-buttons">
<% available_locales.each do |locale| %>
<%= label_tag "default_locale_#{locale}" do %>
<%= radio_button_tag "default_locale", locale, locale == default %>
<%= name_for_locale(locale) %>
<% end %>
<%= f.collection_radio_buttons(
:default,
available_locales,
:to_sym,
->(locale) { name_for_locale(locale) }
) do |b| %>
<%= b.label { b.radio_button + b.text } %>
<% end %>
</div>
</fieldset>
<% end %>
<fieldset>
<legend><%= t("admin.locales.enabled") %></legend>
<legend><%= attribute_name(:enabled) %></legend>
<p class="help-text"><%= t("admin.locales.enabled_help_text") %></p>
<div class="collection-check-boxes">
<% available_locales.each do |locale| %>
<%= label_tag "enabled_locales_#{locale}" do %>
<%= check_box_tag "enabled_locales[]",
locale,
enabled_locales.include?(locale),
id: "enabled_locales_#{locale}" %>
<%= name_for_locale(locale) %>
<% end %>
<%= f.collection_check_boxes(
:enabled,
available_locales,
:to_sym,
->(locale) { name_for_locale(locale) }
) do |b| %>
<%= b.label { b.check_box + b.text } %>
<% end %>
</div>
</fieldset>

View File

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

View File

@@ -1,4 +1,4 @@
<%= header %>
<% 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
include Header
attr_reader :locales, :default
attr_reader :locales_settings
def initialize(locales, default:)
@locales = locales
@default = default
def initialize(locales_settings)
@locales_settings = locales_settings
end
def title

View File

@@ -1,15 +1,27 @@
class Admin::LocalesController < Admin::BaseController
before_action :set_locales_settings
authorize_resource :locales_settings
def show
@enabled_locales = Setting.enabled_locales
@default_locale = Setting.default_locale
end
def update
Setting.transaction do
Setting["locales.default"] = params["default_locale"]
Setting["locales.enabled"] = [params["default_locale"], *params["enabled_locales"]].join(" ")
end
@locales_settings.update!(locales_settings_params)
redirect_to admin_locales_path, notice: t("admin.locales.update.notice")
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

View File

@@ -134,6 +134,8 @@ module Abilities
can [:deliver], Newsletter, hidden_at: nil
can [:manage], Dashboard::AdministratorTask
can :manage, Setting::LocalesSettings
can :manage, LocalCensusRecord
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"
local_census_records/import:
file: File
setting/locales_settings:
default: Default language
enabled: Enabled languages
errors:
models:
local_census_records/import:

View File

@@ -711,9 +711,7 @@ en:
index:
title: Following
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."
enabled: Enabled languages
enabled_help_text: The default language, selected above, will be included automatically.
update:
notice: Languages updated successfully

View File

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

View File

@@ -711,9 +711,7 @@ es:
index:
title: Seguimiento
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."
enabled: Idiomas habilitados
enabled_help_text: El idioma por defecto, seleccionado con anterioridad, se habilitará automáticamente.
update:
notice: Idiomas actualizados con éxito

View File

@@ -3,10 +3,8 @@ require "rails_helper"
describe Admin::Locales::FormComponent do
let(:default_locale) { :nl }
let(:enabled_locales) { %i[en nl] }
let(:component) do
Admin::Locales::FormComponent.new(enabled_locales, default: default_locale)
end
let(:locales_settings) { Setting::LocalesSettings.new(default: default_locale, enabled: enabled_locales) }
let(:component) { Admin::Locales::FormComponent.new(locales_settings) }
describe "default language selector" do
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