diff --git a/lib/primer/open_project/forms/autocompleter.html.erb b/lib/primer/open_project/forms/autocompleter.html.erb index f21b59f522c..04d63c65a95 100644 --- a/lib/primer/open_project/forms/autocompleter.html.erb +++ b/lib/primer/open_project/forms/autocompleter.html.erb @@ -1,26 +1,28 @@ <%= render(FormControl.new(input: @input, data: @wrapper_data_attributes)) do %> - <% if decorated_select? %> - <%= render partial: '/augmented/autocomplete_select_decoration', - formats: %i[html], - locals: { - input_name: @autocomplete_options.fetch(:inputName) { builder.field_name(@input.name) }, - input_id: @autocomplete_options.fetch(:inputId) { builder.field_id(@input.name) }, - select_options: select_options.map(&:to_h), - multiple: @autocomplete_options.fetch(:multiple, false), - key: @autocomplete_options.fetch(:resource, ''), - append_to: @autocomplete_options.fetch(:append_to, 'body') - } %> - <% else %> - <%= content_tag(:div, class: ("projects-autocomplete-with-search-icon" if @autocomplete_options.delete(:with_search_icon))) do %> - <%= angular_component_tag @autocomplete_options.fetch(:component), - data: @autocomplete_options.delete(:data) { {} }, - inputs: @autocomplete_options.merge( - classes: "ng-select--primerized #{@input.invalid? ? '-error' : ''}", - inputName: @autocomplete_options.fetch(:inputName) { builder.field_name(@input.name) }, - inputValue: @autocomplete_options.fetch(:inputValue) { builder.object.send(@input.name) }, - defaultData: @autocomplete_options.fetch(:defaultData) { true } - ) - %> + <%= content_tag(:div, **@field_wrap_arguments) do %> + <% if decorated_select? %> + <%= render partial: '/augmented/autocomplete_select_decoration', + formats: %i[html], + locals: { + input_name: @autocomplete_options.fetch(:inputName) { builder.field_name(@input.name) }, + input_id: @autocomplete_options.fetch(:inputId) { builder.field_id(@input.name) }, + select_options: select_options.map(&:to_h), + multiple: @autocomplete_options.fetch(:multiple, false), + key: @autocomplete_options.fetch(:resource, ''), + append_to: @autocomplete_options.fetch(:append_to, 'body') + } %> + <% else %> + <%= content_tag(:div, class: ("projects-autocomplete-with-search-icon" if @autocomplete_options.delete(:with_search_icon))) do %> + <%= angular_component_tag @autocomplete_options.fetch(:component), + data: @autocomplete_options.delete(:data) { {} }, + inputs: @autocomplete_options.merge( + classes: "ng-select--primerized #{@input.invalid? ? '-error' : ''}", + inputName: @autocomplete_options.fetch(:inputName) { builder.field_name(@input.name) }, + inputValue: @autocomplete_options.fetch(:inputValue) { builder.object.send(@input.name) }, + defaultData: @autocomplete_options.fetch(:defaultData) { true } + ) + %> + <% end %> <% end %> <% end %> <% end %> diff --git a/lib/primer/open_project/forms/autocompleter.rb b/lib/primer/open_project/forms/autocompleter.rb index 3767fd2b071..f2d35812d62 100644 --- a/lib/primer/open_project/forms/autocompleter.rb +++ b/lib/primer/open_project/forms/autocompleter.rb @@ -6,6 +6,7 @@ module Primer # :nodoc: class Autocompleter < Primer::Forms::BaseComponent include AngularHelper + prepend WrappedInput delegate :builder, :form, :select_options, to: :@input diff --git a/lib/primer/open_project/forms/color_select.html.erb b/lib/primer/open_project/forms/color_select.html.erb index ba1af96a830..a6678dce90d 100644 --- a/lib/primer/open_project/forms/color_select.html.erb +++ b/lib/primer/open_project/forms/color_select.html.erb @@ -1,10 +1,12 @@ <%= render(FormControl.new(input: @input)) do %> - <%= builder.hidden_field :color_id %> - <%= angular_component_tag("opce-colors-autocompleter", - class: "colors-autocomplete form--select-container -middle", - data: { - colors:, - classes: "ng-select--primerized", - update_input: "#{builder.object_name}[color_id]" - }) %> + <%= content_tag(:div, **@field_wrap_arguments) do %> + <%= builder.hidden_field :color_id %> + <%= angular_component_tag("opce-colors-autocompleter", + class: "colors-autocomplete form--select-container -middle", + data: { + colors:, + classes: "ng-select--primerized", + update_input: "#{builder.object_name}[color_id]" + }) %> + <% end %> <% end %> diff --git a/lib/primer/open_project/forms/color_select.rb b/lib/primer/open_project/forms/color_select.rb index 35721b81b3c..e24d4ec0251 100644 --- a/lib/primer/open_project/forms/color_select.rb +++ b/lib/primer/open_project/forms/color_select.rb @@ -7,6 +7,7 @@ module Primer class ColorSelect < Primer::Forms::BaseComponent include AngularHelper include ColorsHelper + prepend WrappedInput delegate :builder, :form, to: :@input diff --git a/lib/primer/open_project/forms/wrapped_input.rb b/lib/primer/open_project/forms/wrapped_input.rb new file mode 100644 index 00000000000..51f77fbda23 --- /dev/null +++ b/lib/primer/open_project/forms/wrapped_input.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +# -- copyright +# OpenProject is an open source project management software. +# Copyright (C) 2024 the OpenProject GmbH +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License version 3. +# +# OpenProject is a fork of ChiliProject, which is a fork of Redmine. The copyright follows: +# Copyright (C) 2006-2013 Jean-Philippe Lang +# Copyright (C) 2010-2013 the ChiliProject Team +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# See COPYRIGHT and LICENSE files for more details. +# ++ + +module Primer + module OpenProject + module Forms + # Prepend this module to a subclass of Primer::Forms::BaseComponent. + # Together with a corresponding dom element in the template this will wrap the input field in + # the classes expected by the Primer CSS framework. + # The template of the prepended to class would look like this: + # + # <%= render(FormControl.new(input: @input)) do %> + # <%= content_tag(:div, **@field_wrap_arguments) do %> + # ... actual input field here ... + # <% end %> + # <% end %> + module WrappedInput + extend ActiveSupport::Concern + + included do + raise "This module needs to be prepended." + end + + def initialize(**) + super + + set_field_wrap_arguments + end + + def set_field_wrap_arguments + wrap_classes = [ + "FormControl-input-wrap" + ] + wrap_classes << Primer::Forms::Dsl::Input::INPUT_WIDTH_MAPPINGS[@input.input_width] if @input.input_width + + @field_wrap_arguments = { + class: class_names(wrap_classes), + hidden: @input.hidden? + } + end + end + end + end +end