From c367f217057ac03e3b71e1adb40b9de1d2c79a01 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javi=20Mart=C3=ADn?= Date: Fri, 12 Apr 2024 03:34:22 +0200 Subject: [PATCH] Add buttons to check all/none available languages Although most Consul Democracy installations will only have a few available languages using `config.i18n.available_locales`, there's a chance some installation will keep every language as available and will enable the desired ones using the admin interface. In these cases, enabling (or disabling) every language would be tedious, particularly when casually experimenting in a staging environment or while using the official Consul Democracy demo. So we're adding buttons to simplify the process. Since some installations might have only a couple of available languages, and in this case these buttons would be pretty much useless, we're only showing them when there are many languages available. --- app/assets/javascripts/check_all_none.js | 21 ++++++---- .../admin/locales/form_component.html.erb | 4 ++ .../shared/index_component.html.erb | 5 +-- .../shared/check_all_none_component.html.erb | 12 ++++++ .../shared/check_all_none_component.rb | 7 ++++ .../admin/locales/form_component_spec.rb | 23 ++++++++++- .../shared/check_all_none_component_spec.rb | 41 +++++++++++++++++++ spec/system/admin/locales_spec.rb | 18 ++++++++ 8 files changed, 118 insertions(+), 13 deletions(-) create mode 100644 app/components/shared/check_all_none_component.html.erb create mode 100644 app/components/shared/check_all_none_component.rb create mode 100644 spec/components/shared/check_all_none_component_spec.rb diff --git a/app/assets/javascripts/check_all_none.js b/app/assets/javascripts/check_all_none.js index fddfd1261..99301253f 100644 --- a/app/assets/javascripts/check_all_none.js +++ b/app/assets/javascripts/check_all_none.js @@ -2,15 +2,22 @@ "use strict"; App.CheckAllNone = { initialize: function() { - $("[data-check-all]").on("click", function() { - App.CheckAllNone.associated_fields($(this), "check-all").prop("checked", true); - }); - $("[data-check-none]").on("click", function() { - App.CheckAllNone.associated_fields($(this), "check-none").prop("checked", false); + $(".check-all-none button").on("click", function() { + var fields = App.CheckAllNone.associated_fields($(this)); + + if ($(this).data("check-all")) { + fields.prop("checked", true); + } else if ($(this).data("check-none")) { + fields.prop("checked", false); + } }); }, - associated_fields: function(element, data_attribute) { - return $("[name='" + element.data(data_attribute) + "']"); + associated_fields: function(element) { + if (element.data("field-name")) { + return $("[name='" + element.data("field-name") + "']"); + } else { + return $("[type='checkbox']", element.closest("fieldset")); + } } }; }).call(this); diff --git a/app/components/admin/locales/form_component.html.erb b/app/components/admin/locales/form_component.html.erb index 6c8bbb291..73d9ffb75 100644 --- a/app/components/admin/locales/form_component.html.erb +++ b/app/components/admin/locales/form_component.html.erb @@ -23,6 +23,10 @@ <%= attribute_name(:enabled) %>

<%= t("admin.locales.enabled_help_text") %>

+ <% if many_available_locales? %> + <%= render Shared::CheckAllNoneComponent.new %> + <% end %> +
<%= f.collection_check_boxes( :enabled, diff --git a/app/components/moderation/shared/index_component.html.erb b/app/components/moderation/shared/index_component.html.erb index 67d30d8ef..3366784e3 100644 --- a/app/components/moderation/shared/index_component.html.erb +++ b/app/components/moderation/shared/index_component.html.erb @@ -9,10 +9,7 @@ <% end %> <%= form_tag form_path, method: :put do %> - + <%= render Shared::CheckAllNoneComponent.new(field_name) %> <%= content %> diff --git a/app/components/shared/check_all_none_component.html.erb b/app/components/shared/check_all_none_component.html.erb new file mode 100644 index 000000000..a7c7eda30 --- /dev/null +++ b/app/components/shared/check_all_none_component.html.erb @@ -0,0 +1,12 @@ + diff --git a/app/components/shared/check_all_none_component.rb b/app/components/shared/check_all_none_component.rb new file mode 100644 index 000000000..c03748f12 --- /dev/null +++ b/app/components/shared/check_all_none_component.rb @@ -0,0 +1,7 @@ +class Shared::CheckAllNoneComponent < ApplicationComponent + attr_reader :field_name + + def initialize(field_name = nil) + @field_name = field_name + end +end diff --git a/spec/components/admin/locales/form_component_spec.rb b/spec/components/admin/locales/form_component_spec.rb index ea2398f01..f2ea4be23 100644 --- a/spec/components/admin/locales/form_component_spec.rb +++ b/spec/components/admin/locales/form_component_spec.rb @@ -5,10 +5,9 @@ describe Admin::Locales::FormComponent do let(:enabled_locales) { %i[en nl] } let(:locales_settings) { Setting::LocalesSettings.new(default: default_locale, enabled: enabled_locales) } let(:component) { Admin::Locales::FormComponent.new(locales_settings) } + before { allow(I18n).to receive(:available_locales).and_return(%i[de en es nl]) } describe "default language selector" do - before { allow(I18n).to receive(:available_locales).and_return(%i[de en es nl]) } - it "renders radio buttons when there are only a few locales" do render_inline component @@ -34,4 +33,24 @@ describe Admin::Locales::FormComponent do selected: "Nederlands" end end + + describe "buttons to check all/none" do + it "is not rendered when there are only a few locales" do + render_inline component + + expect(page).not_to have_button "Select all" + expect(page).not_to have_button "Select none" + end + + it "is rendered when there are many locales" do + allow(component).to receive(:select_field_threshold).and_return(3) + + render_inline component + + page.find(:fieldset, "Enabled languages") do |fieldset| + expect(fieldset).to have_button "Select all" + expect(fieldset).to have_button "Select none" + end + end + end end diff --git a/spec/components/shared/check_all_none_component_spec.rb b/spec/components/shared/check_all_none_component_spec.rb new file mode 100644 index 000000000..fcf1510fa --- /dev/null +++ b/spec/components/shared/check_all_none_component_spec.rb @@ -0,0 +1,41 @@ +require "rails_helper" + +describe Shared::CheckAllNoneComponent do + it "generates a data-field-name attribute when a field name is given" do + render_inline Shared::CheckAllNoneComponent.new("ids[]") + + expect(page).to have_button count: 2 + + page.find("li:first-child") do |check_all| + expect(check_all).to have_button "Select all" + expect(check_all).to have_css "button[type='button'][data-field-name='ids[]'][data-check-all]" + expect(check_all).not_to have_css "[data-check-none]" + end + + page.find("li:last-child") do |check_none| + expect(check_none).to have_button "Select none" + expect(check_none).to have_css "button[type='button'][data-field-name='ids[]'][data-check-none]" + expect(check_none).not_to have_css "[data-check-all]" + end + end + + it "does not generate a data-field-name attribute when no field name is given" do + render_inline Shared::CheckAllNoneComponent.new + + expect(page).to have_button count: 2 + + page.find("li:first-child") do |check_all| + expect(check_all).to have_button "Select all" + expect(check_all).to have_css "button[type='button'][data-check-all]" + expect(check_all).not_to have_css "[data-check-none]" + expect(check_all).not_to have_css "[data-field-name]" + end + + page.find("li:last-child") do |check_none| + expect(check_none).to have_button "Select none" + expect(check_none).to have_css "button[type='button'][data-check-none]" + expect(check_none).not_to have_css "[data-check-all]" + expect(check_none).not_to have_css "[data-field-name]" + end + end +end diff --git a/spec/system/admin/locales_spec.rb b/spec/system/admin/locales_spec.rb index 46b5ee2a2..bdc4c6b18 100644 --- a/spec/system/admin/locales_spec.rb +++ b/spec/system/admin/locales_spec.rb @@ -51,4 +51,22 @@ describe "Locales management", :admin do expect(page).not_to have_link "English" end end + + scenario "select all/none" do + allow_any_instance_of(Admin::Locales::FormComponent).to receive(:many_available_locales?).and_return(true) + + visit admin_locales_path + + within_fieldset "Enabled languages" do + expect(page).to have_field type: :checkbox + + click_button "Select all" + + expect(all(:checkbox)).to all(be_checked) + + click_button "Select none" + + all(:checkbox).each { |checkbox| expect(checkbox).not_to be_checked } + end + end end