diff --git a/app/forms/login_form.rb b/app/forms/login_form.rb index 2e9d7cc1dfb4..d77e4a938351 100644 --- a/app/forms/login_form.rb +++ b/app/forms/login_form.rb @@ -55,37 +55,28 @@ class LoginForm < ApplicationForm autocomplete: "current-password" ) - if Setting::Autologin.enabled? - f.check_box name: "autologin", - id: "autologin#{@id_suffix}", - checked: false, - value: 1, - label: I18n.t("users.autologins.prompt", - num_days: I18n.t("datetime.distance_in_words.x_days", count: Setting.autologin)) - end - - f.html_content do - flex_layout(justify_content: :space_between, align_items: :center) do |flex| - flex.with_column do - render(Primer::Beta::Button.new(type: :submit, scheme: :primary)) { I18n.t(:button_login) } - end + f.group(layout: :horizontal, + justify_content: Setting::Autologin.enabled? ? :space_between : :flex_end, + align_items: :center) do |g| + if Setting::Autologin.enabled? + g.check_box name: "autologin", + id: "autologin#{@id_suffix}", + checked: false, + value: 1, + label: I18n.t("users.autologins.prompt", + num_days: I18n.t("datetime.distance_in_words.x_days", count: Setting.autologin)) + end - flex.with_column do - flex_layout do |links| - if Setting::SelfRegistration.enabled? - links.with_row do - render(Primer::Beta::Link.new(href: url_helpers.account_register_path)) { I18n.t(:label_register) } - end - end - if Setting.lost_password? - links.with_row do - render(Primer::Beta::Link.new(href: url_helpers.account_lost_password_path)) { I18n.t(:label_password_lost) } - end - end - end + if Setting.lost_password? + g.html_content do + render(Primer::Beta::Link.new(href: url_helpers.account_lost_password_path)) { I18n.t(:label_password_lost) } end end end + + f.html_content do + render(Primer::Beta::Button.new(type: :submit, scheme: :primary, block: true)) { I18n.t(:button_login) } + end end def initialize(back_url: nil, username: nil, id_suffix: nil) diff --git a/app/forms/registration_form.rb b/app/forms/registration_form.rb index 2a1cdbd981af..eb4a49567ff5 100644 --- a/app/forms/registration_form.rb +++ b/app/forms/registration_form.rb @@ -55,7 +55,9 @@ class RegistrationForm < ApplicationForm consent(f) if helpers.user_consent_required? - f.submit(name: :submit, label: I18n.t(:button_create), scheme: :primary) + f.html_content do + render(Primer::Beta::Button.new(type: :submit, scheme: :primary, block: true)) { I18n.t(:button_create) } + end registration_footer(f) end diff --git a/app/forms/settings/input_methods.rb b/app/forms/settings/input_methods.rb index fbb74d52dd2e..81214d972858 100644 --- a/app/forms/settings/input_methods.rb +++ b/app/forms/settings/input_methods.rb @@ -203,27 +203,30 @@ def select_list(name:, values: nil, option_options: {}, **, &block) end def multi_language_text_select(name:, current_language: I18n.locale.to_s) - # Add select list to switch - object.select_list( - name: :"#{name}_lang", # Should be excluded by settings params - input_width: :small, - id: "lang-for-#{name}", - class: "lang-select-switch", - label: setting_label(name), - caption: setting_caption(name), - include_blank: false - ) do |select| - lang_options_for_select(false).each do |label, value| - select.option( - value:, - label:, - selected: value == current_language - ) + object.group(data: { controller: "admin--multi-lang-text-setting" }) do |group| + # Add select list to switch + group.select_list( + name: :"#{name}_lang", # Should be excluded by settings params + input_width: :small, + id: "lang-for-#{name}", + class: "lang-select-switch", + label: setting_label(name), + caption: setting_caption(name), + include_blank: false, + data: { admin__multi_lang_text_setting_target: "select" } + ) do |select| + lang_options_for_select(false).each do |label, value| + select.option( + value:, + label:, + selected: value == current_language + ) + end end - end - object.fields_for(name) do |builder| - MultiLangForm.new(builder, name:, current_language:) + group.fields_for(name) do |builder| + MultiLangForm.new(builder, name:, current_language:) + end end end diff --git a/app/forms/settings/multi_lang_form.rb b/app/forms/settings/multi_lang_form.rb index b13a92afc773..2dc8c977b604 100644 --- a/app/forms/settings/multi_lang_form.rb +++ b/app/forms/settings/multi_lang_form.rb @@ -47,7 +47,8 @@ def initialize(name:, current_language:) f.hidden( name: lang, value: Setting.send(name)[lang], - id: "lang-for-#{name}-#{lang}" + id: "lang-for-#{name}-#{lang}", + data: { admin__multi_lang_text_setting_target: "langFor", lang: } ) end @@ -58,6 +59,7 @@ def initialize(name:, current_language:) label: setting_label(name), disabled: setting_disabled?(name), visually_hide_label: true, + data: { admin__multi_lang_text_setting_target: "textArea" }, rich_text_options: { turboMode: true, showAttachments: false diff --git a/app/helpers/omniauth_helper.rb b/app/helpers/omniauth_helper.rb index ad09f94f5a8d..39114f4fd820 100644 --- a/app/helpers/omniauth_helper.rb +++ b/app/helpers/omniauth_helper.rb @@ -43,16 +43,17 @@ def omniauth_login_path_options end end - def omniauth_provider_button(name, display_name: nil, icon: false) - classes = ["auth-provider", "auth-provider-#{name}", "button"] - classes << "auth-provider--imaged" if icon + def omniauth_provider_button(name, display_name: nil, icon: nil) + render(Primer::Beta::Button.new(tag: :a, + href: omniauth_login_path(name, omniauth_login_path_options), + block: true, + align_content: :center, + classes: "auth-provider auth-provider-#{name}", + data: { turbo: false })) do + label = tag.span(provider_button_label(name, display_name), class: "auth-provider-name") + parts = icon.present? ? [image_tag(icon, alt: "", class: "auth-provider-icon"), label] : [label] - link_to( - omniauth_login_path(name, omniauth_login_path_options), - class: classes.join(" "), - data: { turbo: false } - ) do - tag.span(display_name.presence || name, class: "auth-provider-name") + render(Primer::Alpha::Stack.new(direction: :horizontal, align: :center, gap: :condensed)) { safe_join(parts) } end end @@ -70,6 +71,20 @@ def direct_login_provider Setting.omniauth_direct_login_provider.presence end + def provider_button_label(name, display_name) + I18n.t("account.continue_with_provider", name: display_name.presence || name) + end + + # Returns nil unless the hook produced actual provider markup. In development + # Rails annotates every rendered partial with HTML comments, so a hook that + # rendered nothing still comes back non-blank. + def auth_provider_html + html = call_hook :view_account_login_auth_provider + content = Rails.env.development? ? html.gsub(//m, "") : html + + html if content.present? + end + # Uses the controller-assigned flag so /login/internal can still render the # password form when instance-wide password login is off. def show_password_login_form? diff --git a/app/views/account/_auth_providers.html.erb b/app/views/account/_auth_providers.html.erb index ba581dac6280..6bf67ce1aeef 100644 --- a/app/views/account/_auth_providers.html.erb +++ b/app/views/account/_auth_providers.html.erb @@ -35,22 +35,28 @@ See COPYRIGHT and LICENSE files for more details. # See # * https://community.openproject.org/work_packages/7192 # * http://stackoverflow.com/questions/13112430/find-loaded-providers-for-omniauth -auth_provider_html = call_hook :view_account_login_auth_provider +providers_html = auth_provider_html no_pwd = Users::PasswordLogin.none? && !@force_password_login_form -pclass = no_pwd ? "no-pwd" : "" -wclass = local_assigns[:wide] ? "wide" : "" +# Without a password form above there is nothing to separate the section from. +spacing = no_pwd ? { mt: 0 } : { mt: 4, pt: 4, border: :top } +title = Primer::Beta::Heading.new( + tag: :h3, + classes: "login-auth-providers-title", + font_size: 4, + font_weight: :bold, + text_align: :center, + mb: 3 +) %> -<% if auth_provider_html.present? %> -