diff --git a/app/components/custom_fields/custom_options/base_row_component.rb b/app/components/custom_fields/custom_options/base_row_component.rb new file mode 100644 index 000000000000..cd20942429dd --- /dev/null +++ b/app/components/custom_fields/custom_options/base_row_component.rb @@ -0,0 +1,128 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module CustomOptions + class BaseRowComponent < ::RowComponent + with_collection_parameter :row + + alias :custom_option :model + + delegate :form, :custom_field, to: :table + + attr_reader :index, :templated + + def initialize(row_counter:, templated: false, **) + @index = row_counter || "INDEX" + @templated = templated + + super + end + + def button_links + [ + primer_action_button( + icon: :"move-to-top", + label: t(:label_sort_highest), + data: { action: "admin--custom-fields#moveRowToTheTop" } + ), + + primer_action_button( + icon: :"arrow-up", + label: t(:label_sort_higher), + data: { action: "admin--custom-fields#moveRowUp" } + ), + + primer_action_button( + icon: :"arrow-down", + label: t(:label_sort_lower), + data: { action: "admin--custom-fields#moveRowDown" } + ), + + primer_action_button( + icon: :"move-to-bottom", + label: t(:label_sort_lowest), + data: { action: "admin--custom-fields#moveRowToTheBottom" } + ), + + primer_action_button( + icon: :trash, + label: t(:button_delete), + data: { + action: "admin--custom-fields#removeOption", + turbo_method: :delete, + turbo_confirm: t(:"custom_fields.confirm_destroy_option") + } + ) + ] + end + + def row_css_class + "dragula-element custom-option-row" + end + + def prefix + raise NotImplementedError + end + + private + + def primer_text_field(name:, **) + with_form do |f| + f.text_field(name:, visually_hide_label: true, **) + end + end + + def primer_check_box(name:, **, &) + with_form do |f| + f.check_box(name:, visually_hide_label: true, **, &) + end + end + + def primer_action_button(icon:, label:, **system_arguments) + render( + Primer::Beta::IconButton.new( + scheme: :invisible, + icon:, + tooltip_direction: :se, + aria: { label: }, + **system_arguments + ) + ) + end + + def with_form(&) + form.fields_for(prefix, custom_option) do |fields| + render_inline_form(fields, &) + end + end + end + end +end diff --git a/app/components/custom_fields/custom_options/row_component.rb b/app/components/custom_fields/custom_options/row_component.rb new file mode 100644 index 000000000000..a79c1957408b --- /dev/null +++ b/app/components/custom_fields/custom_options/row_component.rb @@ -0,0 +1,55 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module CustomOptions + class RowComponent < BaseRowComponent + def value + # safe_join([ + # hidden_field :id, disabled: true + # ]) + primer_text_field(name: :value, label: CustomOption.human_attribute_name(:value)) + end + + def default_value + primer_check_box( + name: :default_value, + label: t(:label_default), + data: { + "admin--custom-fields-target": "customOptionDefaults", + action: "admin--custom-fields#uncheckOtherDefaults" + } + ) + end + + def prefix = :custom_options + end + end +end diff --git a/app/components/custom_fields/custom_options/table_component.rb b/app/components/custom_fields/custom_options/table_component.rb new file mode 100644 index 000000000000..358a2ce5f02e --- /dev/null +++ b/app/components/custom_fields/custom_options/table_component.rb @@ -0,0 +1,69 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module CustomOptions + class TableComponent < ::TableComponent + options :form + options :custom_field + + columns :value, :default_value + + def row_class + RowComponent + end + + def headers + [ + ["value", { caption: CustomOption.human_attribute_name(:value) }], + ["default_value", { caption: t(:label_default) }] + ] + end + + def sortable? + false + end + + def inline_create_link + render( + Primer::Beta::IconButton.new( + scheme: :invisible, + icon: :plus, + tooltip_direction: :e, + aria: { label: t(:button_add) }, + data: { action: "admin--custom-fields#addOption" }, + test_selector: "add-custom-option", + mt: 2 + ) + ) + end + end + end +end diff --git a/app/components/custom_fields/custom_options_component.html.erb b/app/components/custom_fields/custom_options_component.html.erb new file mode 100644 index 000000000000..98689d883777 --- /dev/null +++ b/app/components/custom_fields/custom_options_component.html.erb @@ -0,0 +1,48 @@ +<%#-- copyright +OpenProject is an open source project management software. +Copyright (C) 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. + +++#%> + + +<% if custom_field.persisted? %> +
+ + <%= link_to t("custom_fields.reorder_alphabetical"), + { action: :reorder_alphabetical }, + data: { + turbo_method: :post, + turbo_confirm: t("custom_fields.reorder_confirmation") + } %> + +
+<% end %> + +<%= render(table) %> + + + <%= render(template_row) %> +
diff --git a/app/components/custom_fields/custom_options_component.rb b/app/components/custom_fields/custom_options_component.rb new file mode 100644 index 000000000000..b8dc06f37ba0 --- /dev/null +++ b/app/components/custom_fields/custom_options_component.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + class CustomOptionsComponent < ApplicationComponent + extend Dry::Initializer + + option :form + option :custom_field + + attr_reader :custom_options, :template_object + + def initialize(...) + super + + @custom_options = @custom_field.custom_options + @template_object = @custom_options.build + end + + private + + def table + @table ||= CustomOptions::TableComponent.new( + rows: custom_options, + form:, + custom_field:, + table_arguments: { + id: "custom_options", + data: { admin__custom_fields_target: "table" } + } + ) + end + + def template_row + CustomOptions::RowComponent.new(row: template_object, row_counter: nil, table:, templated: true) + end + end +end diff --git a/app/components/table_component.html.erb b/app/components/table_component.html.erb index f31253674354..9e1c00c35b19 100644 --- a/app/components/table_component.html.erb +++ b/app/components/table_component.html.erb @@ -29,7 +29,7 @@ See COPYRIGHT and LICENSE files for more details.
- + <%= render(Primer::BaseComponent.new(**@system_arguments)) do %> <% headers.each do |_name, _options| %> @@ -67,7 +67,7 @@ See COPYRIGHT and LICENSE files for more details. <% end %> <%= render_collection rows %> -
+ <% end %> <% if inline_create_link %>
<%= inline_create_link %> diff --git a/app/components/table_component.rb b/app/components/table_component.rb index 369f8a9c69cf..a5ab35781ee9 100644 --- a/app/components/table_component.rb +++ b/app/components/table_component.rb @@ -31,8 +31,17 @@ ## # Abstract view component. Subclass this for a concrete table. class TableComponent < ApplicationComponent - def initialize(rows: [], **) + def initialize(rows: [], table_arguments: {}, **) super(rows, **) + + @system_arguments = table_arguments + @system_arguments[:tag] = :table + @system_arguments[:classes] = class_names( + @system_arguments[:classes], + "generic-table" + ) + @system_arguments[:data] ||= {} + @system_arguments[:data][:controller] = "table-highlighting" end class << self diff --git a/app/forms/custom_fields/details/admin_only_form.rb b/app/forms/custom_fields/details/admin_only_form.rb new file mode 100644 index 000000000000..aa208f4bccb2 --- /dev/null +++ b/app/forms/custom_fields/details/admin_only_form.rb @@ -0,0 +1,43 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class AdminOnlyForm < BaseForm + form do |f| + f.check_box( + name: :admin_only, + label: attribute_name(:admin_only), + caption: I18n.t("custom_fields.instructions.admin_only") + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/allow_non_open_versions_form.rb b/app/forms/custom_fields/details/allow_non_open_versions_form.rb new file mode 100644 index 000000000000..5295758f2ab3 --- /dev/null +++ b/app/forms/custom_fields/details/allow_non_open_versions_form.rb @@ -0,0 +1,48 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class AllowNonOpenVersionsForm < BaseForm + supports_formats only: %i[version] + + form do |f| + f.check_box( + name: :allow_non_open_versions, + label: attribute_name(:allow_non_open_versions) + ) + end + + def render? + super && model.allow_non_open_versions_possible? + end + end + end +end diff --git a/app/forms/custom_fields/details/base_form.rb b/app/forms/custom_fields/details/base_form.rb new file mode 100644 index 000000000000..b6b7bf4bf8a7 --- /dev/null +++ b/app/forms/custom_fields/details/base_form.rb @@ -0,0 +1,71 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class BaseForm < ApplicationForm + ALLOWED_SUPPORTED_FORMATS_OPERATORS = %i[only except].freeze + private_constant :ALLOWED_SUPPORTED_FORMATS_OPERATORS + + delegate :supported_formats_config, to: :class, private: true + + class << self + def supports_formats(config = {}) + @supported_formats_config = config.transform_values { |formats| Array(formats).map(&:to_sym) } + end + + def supported_formats_config + @supported_formats_config ||= {} + end + end + + def render? + supported_format? + end + + private + + def instructions_for(attribute) + I18n.t(attribute, scope: %i[custom_fields instructions]) + end + + def supported_format? + @supported_format ||= begin + field_format = model.field_format.to_sym + case supported_formats_config + in { only: } then only.include?(field_format) + in { except: } then except.exclude?(field_format) + else true + end + end + end + end + end +end diff --git a/app/forms/custom_fields/details/default_bool_form.rb b/app/forms/custom_fields/details/default_bool_form.rb new file mode 100644 index 000000000000..b039ca0bb22d --- /dev/null +++ b/app/forms/custom_fields/details/default_bool_form.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class DefaultBoolForm < BaseForm + supports_formats only: %i[bool] + + form do |f| + f.check_box( + name: :default_value, + label: attribute_name(:default_value) + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/default_long_text_form.rb b/app/forms/custom_fields/details/default_long_text_form.rb new file mode 100644 index 000000000000..e5604257e00d --- /dev/null +++ b/app/forms/custom_fields/details/default_long_text_form.rb @@ -0,0 +1,45 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class DefaultLongTextForm < BaseForm + supports_formats only: %i[text] + + form do |f| + f.rich_text_area( + name: :default_value, + label: attribute_name(:default_value), + rich_text_options: { resource: nil, macros: :none } + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/default_text_form.rb b/app/forms/custom_fields/details/default_text_form.rb new file mode 100644 index 000000000000..20fb1aecdc13 --- /dev/null +++ b/app/forms/custom_fields/details/default_text_form.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class DefaultTextForm < BaseForm + supports_formats except: %i[list bool date text user version hierarchy calculated_value] + + form do |f| + f.text_field( + name: :default_value, + label: attribute_name(:default_value) + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/length_form.rb b/app/forms/custom_fields/details/length_form.rb new file mode 100644 index 000000000000..61bb40f4438d --- /dev/null +++ b/app/forms/custom_fields/details/length_form.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class LengthForm < BaseForm + supports_formats except: %i[list bool date user version link hierarchy calculated_value] + + form do |f| + f.group(layout: :horizontal) do |g| + g.text_field( + name: :min_length, + type: :number, + label: attribute_name(:min_length), + caption: I18n.t(:text_min_max_length_info), + input_width: :xsmall + ) + + g.text_field( + name: :max_length, + type: :number, + label: attribute_name(:max_length), + caption: I18n.t(:text_min_max_length_info), + input_width: :xsmall + ) + end + end + end + end +end diff --git a/app/forms/custom_fields/details/multi_select_form.rb b/app/forms/custom_fields/details/multi_select_form.rb new file mode 100644 index 000000000000..f7a6bcfc3398 --- /dev/null +++ b/app/forms/custom_fields/details/multi_select_form.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class MultiSelectForm < BaseForm + supports_formats only: %i[list user version hierarchy] + + form do |f| + f.check_box( + name: :multi_value, + label: attribute_name(:multi_value), + caption: instructions_for(:multi_select), + data: { action: "admin--custom-fields#checkOnlyOne" } + ) + end + + def render? + super && model.multi_value_possible? + end + end + end +end diff --git a/app/forms/custom_fields/details/name_form.rb b/app/forms/custom_fields/details/name_form.rb new file mode 100644 index 000000000000..259ee1083892 --- /dev/null +++ b/app/forms/custom_fields/details/name_form.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class NameForm < BaseForm + form do |f| + f.text_field( + name: :name, + label: attribute_name(:name), + required: true, + data: { test_selector: "op-custom-fields--new-custom-field-name" } + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/possible_values_form.rb b/app/forms/custom_fields/details/possible_values_form.rb new file mode 100644 index 000000000000..764502ed3704 --- /dev/null +++ b/app/forms/custom_fields/details/possible_values_form.rb @@ -0,0 +1,40 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class PossibleValuesForm < BaseForm + # supports_formats only: %i[list user version hierarchy] + + form do |f| + end + end + end +end diff --git a/app/forms/custom_fields/details/project_attribute_section_form.rb b/app/forms/custom_fields/details/project_attribute_section_form.rb new file mode 100644 index 000000000000..b169a103aaca --- /dev/null +++ b/app/forms/custom_fields/details/project_attribute_section_form.rb @@ -0,0 +1,57 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class ProjectAttributeSectionForm < BaseForm + form do |f| + f.select_list( + name: :custom_field_section_id, + label: ProjectCustomField.human_attribute_name(:custom_field_section), + required: true + ) do |list| + available_attribute_sections.each do |label, value| + list.option(label:, value:) + end + end + end + + def render? + super && model.is_a?(ProjectCustomField) + end + + private + + def available_attribute_sections + ProjectCustomFieldSection.pluck(:name, :id) + end + end + end +end diff --git a/app/forms/custom_fields/details/regexp_form.rb b/app/forms/custom_fields/details/regexp_form.rb new file mode 100644 index 000000000000..e7843c17bfa2 --- /dev/null +++ b/app/forms/custom_fields/details/regexp_form.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class RegexpForm < BaseForm + supports_formats except: %i[list bool date user version hierarchy calculated_value] + + form do |f| + f.text_field( + name: :regexp, + label: attribute_name(:regexp), + size: 50, + caption: I18n.t(:text_regexp_info) + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/required_form.rb b/app/forms/custom_fields/details/required_form.rb new file mode 100644 index 000000000000..f77541b3c664 --- /dev/null +++ b/app/forms/custom_fields/details/required_form.rb @@ -0,0 +1,47 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class RequiredForm < BaseForm + extend Dry::Initializer + + option :for_project, default: -> { false } + + form do |f| + f.check_box( + name: :is_required, + label: attribute_name(:is_required), + caption: for_project ? instructions_for(:is_required_for_project) : instructions_for(:is_required) + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/right_to_left_form.rb b/app/forms/custom_fields/details/right_to_left_form.rb new file mode 100644 index 000000000000..5c375ba20672 --- /dev/null +++ b/app/forms/custom_fields/details/right_to_left_form.rb @@ -0,0 +1,44 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class RightToLeftForm < BaseForm + supports_formats only: %i[text] + + form do |f| + f.check_box( + name: :content_right_to_left, + label: attribute_name(:content_right_to_left) + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/searchable_form.rb b/app/forms/custom_fields/details/searchable_form.rb new file mode 100644 index 000000000000..301f94d2af85 --- /dev/null +++ b/app/forms/custom_fields/details/searchable_form.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class SearchableForm < BaseForm + extend Dry::Initializer + + supports_formats except: %i[bool date float int user version hierarchy calculated_value] + + option :for_project, default: -> { false } + + form do |f| + f.check_box( + name: :searchable, + label: attribute_name(:searchable), + caption: for_project ? instructions_for(:searchable_for_project) : instructions_for(:searchable) + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/user_custom_field_form.rb b/app/forms/custom_fields/details/user_custom_field_form.rb new file mode 100644 index 000000000000..13aff78d79de --- /dev/null +++ b/app/forms/custom_fields/details/user_custom_field_form.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class UserCustomFieldForm < BaseForm + form do |f| + f.check_box( + name: :admin_only, + label: attribute_name(:admin_only), + caption: instructions_for(:admin_only) + ) + + f.check_box( + name: :editable, + label: attribute_name(:editable), + caption: instructions_for(:admin_only) + ) + end + end + end +end diff --git a/app/forms/custom_fields/details/work_package_custom_field_form.rb b/app/forms/custom_fields/details/work_package_custom_field_form.rb new file mode 100644 index 000000000000..eee72314fac1 --- /dev/null +++ b/app/forms/custom_fields/details/work_package_custom_field_form.rb @@ -0,0 +1,49 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + module Details + class WorkPackageCustomFieldForm < BaseForm + form do |f| + f.check_box( + name: :is_for_all, + label: attribute_name(:is_for_all), + caption: instructions_for(:is_for_all) + ) + + f.check_box( + name: :is_filter, + label: attribute_name(:is_filter), + caption: instructions_for(:is_filter) + ) + end + end + end +end diff --git a/app/forms/custom_fields/save.rb b/app/forms/custom_fields/save.rb new file mode 100644 index 000000000000..f31f51473815 --- /dev/null +++ b/app/forms/custom_fields/save.rb @@ -0,0 +1,46 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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 CustomFields + class Save < ApplicationForm + attr_reader :label, :system_arguments + + form do |f| + f.submit(scheme: :primary, name: :submit, label:, **system_arguments) + end + + def initialize(label: I18n.t(:button_save), **system_arguments) + super() + + @label = label + @system_arguments = system_arguments + end + end +end diff --git a/app/views/admin/settings/project_custom_fields/edit.html.erb b/app/views/admin/settings/project_custom_fields/edit.html.erb index 644f966d3a06..367c86f153d5 100644 --- a/app/views/admin/settings/project_custom_fields/edit.html.erb +++ b/app/views/admin/settings/project_custom_fields/edit.html.erb @@ -45,15 +45,20 @@ See COPYRIGHT and LICENSE files for more details. <% content_controller "admin--custom-fields", "admin--custom-fields-format-value": @custom_field.field_format, - "admin--custom-fields-format-config-value": OpenProject::CustomFieldFormatDependent.stimulus_config %> + "admin--custom-fields-item-count-value": @custom_field.custom_options.size %> - <%= labelled_tabular_form_for @custom_field, as: :custom_field, - url: admin_settings_project_custom_field_path(@custom_field), - html: { method: :put, id: "custom_field_form" } do |f| %> - <%= render partial: "custom_fields/form", locals: { f: f, custom_field: @custom_field } %> + <%= + settings_primer_form_with( + model: @custom_field, + scope: :custom_field, + url: admin_settings_project_custom_field_path(@custom_field), + html: { method: :put, id: "custom_field_form" } + ) do |f| + %> + <%= render partial: "custom_fields/form", locals: { f: } %> <% if @custom_field.new_record? %> <%= hidden_field_tag "type", @custom_field.type %> <% end %> - <%= styled_button_tag t(:button_save), class: "-highlight -with-icon icon-checkmark" %> + <%= render CustomFields::Save.new(f) %> <% end %> <% end %> diff --git a/app/views/admin/settings/project_custom_fields/new.html.erb b/app/views/admin/settings/project_custom_fields/new.html.erb index d36d93794f2c..a4197cac8527 100644 --- a/app/views/admin/settings/project_custom_fields/new.html.erb +++ b/app/views/admin/settings/project_custom_fields/new.html.erb @@ -38,15 +38,20 @@ See COPYRIGHT and LICENSE files for more details. <% content_controller "admin--custom-fields", "admin--custom-fields-format-value": @custom_field.field_format, - "admin--custom-fields-format-config-value": OpenProject::CustomFieldFormatDependent.stimulus_config %> - - <%= labelled_tabular_form_for @custom_field, as: :custom_field, - url: admin_settings_project_custom_fields_path, - html: { id: "custom_field_form" } do |f| %> - <%= render partial: "custom_fields/form", locals: { f: f, custom_field: @custom_field } %> + "admin--custom-fields-item-count-value": @custom_field.custom_options.size %> + + <%= + settings_primer_form_with( + model: @custom_field, + scope: :custom_field, + url: admin_settings_project_custom_fields_path, + html: { id: "custom_field_form" } + ) do |f| + %> + <%= render partial: "custom_fields/form", locals: { f: } %> <% if @custom_field.new_record? %> <%= hidden_field_tag "type", @custom_field.type %> <% end %> - <%= styled_button_tag t(:button_save), class: "-highlight -with-icon icon-checkmark" %> + <%= render CustomFields::Save.new(f) %> <% end %> <% end %> diff --git a/app/views/custom_fields/_custom_options.html.erb b/app/views/custom_fields/_custom_options.html.erb deleted file mode 100644 index 4684985f9b53..000000000000 --- a/app/views/custom_fields/_custom_options.html.erb +++ /dev/null @@ -1,159 +0,0 @@ -<%#-- copyright -OpenProject is an open source project management software. -Copyright (C) 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. - -++#%> - -<% custom_field = f.object %> -<% custom_field.custom_options.build if custom_field.custom_options.empty? %> - -
-
- - - - - - - - - - - - - - - - - - <% custom_field.custom_options.each_with_index do |custom_option, i| %> - <%= f.fields_for :custom_options, custom_option do |co_f| %> - - - - - - - <% end %> - <% end %> - -
-
-
- - <%= t("activerecord.attributes.custom_value.value") %> - -
-
-
-
-
- - <%= t(:label_default) %> - -
-
-
-
-
- - <%= t(:button_sort) %> - -
-
-
-
-
-
- - <%= co_f.hidden_field :id, - disabled: true, - class: "custom-option-id" %> - <%= co_f.text_field :value, - disabled: true, - container_class: "custom-option-value", - no_label: true %> - - <%= co_f.check_box :default_value, - disabled: true, - container_class: "custom-option-default-value", - data: { - "admin--custom-fields-target": "customOptionDefaults", - action: "admin--custom-fields#uncheckOtherDefaults" - }, - no_label: true %> - - - - <%= op_icon("icon-context icon-sort-up icon-small") %> - - - <%= op_icon("icon-context icon-arrow-up2 icon-small") %> - - - <%= op_icon("icon-context icon-arrow-down2 icon-small") %> - - - <%= op_icon("icon-context icon-sort-down icon-small") %> - - - - <%= link_to "", - delete_option_of_custom_field_path(id: custom_field.id || 0, option_id: custom_option.id || 0), - data: { - turbo_method: :delete, - action: "admin--custom-fields#removeOption", - turbo_confirm: t(:"custom_fields.confirm_destroy_option") - }, - class: "icon icon-delete delete-custom-option", - title: t(:button_delete) %> -
- -
-
diff --git a/app/views/custom_fields/_form.html.erb b/app/views/custom_fields/_form.html.erb index bab5ef3c4a89..7d1da90ea0e4 100644 --- a/app/views/custom_fields/_form.html.erb +++ b/app/views/custom_fields/_form.html.erb @@ -25,227 +25,77 @@ Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. See COPYRIGHT and LICENSE files for more details. -++# %> - -<% format_dependent = OpenProject::CustomFieldFormatDependent.new(@custom_field.field_format) %> - -
+++#%> +<%# locals: (f:) %> +
<%= f.hidden_field :field_format if @custom_field.new_record? %> -
- <%= f.text_field :name, - required: true, - container_class: "-middle", - "data-test-selector": "op-custom-fields--new-custom-field-name" %> -
- <% if @custom_field.type == 'ProjectCustomField' %> -
- <%= f.select :custom_field_section_id, - ProjectCustomFieldSection.all.collect { |s| [s.name, s.id] }, - { container_class: "-slim" }, - required: true %> -
- <% end %> - -
> -
- <%= t(:label_min_max_length) %>
- (<%= t(:text_min_max_length_info) %>) -
-
-
- <%= f.number_field :min_length, - container_class: "-xslim" %> -
-
- <%= f.number_field :max_length, - container_class: "-xslim" %> -
-
-
- -
> - <%= f.text_field :regexp, - size: 50, - container_class: "-wide" %> - - <%= t(:text_regexp_info) %> - -
- - <% if @custom_field.new_record? || @custom_field.multi_value_possible? %> -
> - <%= f.check_box :multi_value, - data: { action: "admin--custom-fields#checkOnlyOne" } %> -
-

- <% if @custom_field.is_a?(ProjectCustomField) %> - <%= t("custom_fields.instructions.multi_select.project") %> - <% else %> - <%= t("custom_fields.instructions.multi_select.all") %> - <% end %> -

-
-
- -
> - <%= I18n.t("activerecord.attributes.custom_field.possible_values") %> - <% if @custom_field.persisted? %> -
- - <%= link_to t("custom_fields.reorder_alphabetical"), - { action: :reorder_alphabetical }, - data: { - turbo_method: :post, - turbo_confirm: t("custom_fields.reorder_confirmation") - } %> - -
- <% end %> -
- <%= render partial: "custom_fields/custom_options", locals: { custom_field: @custom_field, f: f } %> - <%= - render Primer::Beta::Button.new( - scheme: :link, - test_selector: "add-custom-option", - data: { action: "admin--custom-fields#addOption" }, - mt: 2 - ) do |button| - button.with_leading_visual_icon(icon: :plus) - t(:button_add) - end - %> -
-
- <% end %> - - <% if @custom_field.new_record? || @custom_field.allow_non_open_versions_possible? %> -
> - <%= f.check_box :allow_non_open_versions %> -
- <% end %> + <%= + render( + Primer::Forms::FormList.new( + CustomFields::Details::NameForm.new(f), + CustomFields::Details::ProjectAttributeSectionForm.new(f), + CustomFields::Details::LengthForm.new(f), + CustomFields::Details::RegexpForm.new(f), + CustomFields::Details::MultiSelectForm.new(f), + CustomFields::Details::PossibleValuesForm.new(f), + CustomFields::Details::AllowNonOpenVersionsForm.new(f), + CustomFields::Details::DefaultBoolForm.new(f), + CustomFields::Details::DefaultLongTextForm.new(f), + CustomFields::Details::DefaultTextForm.new(f) + ) + ) + %> + + <%= I18n.t("activerecord.attributes.custom_field.possible_values") %> + <%# format_dependent.attributes(:possibleValues) %> + <%= render(CustomFields::CustomOptionsComponent.new(form: f, custom_field: @custom_field)) %> - <% if @custom_field.new_record? || !%w[text bool].include?(@custom_field.field_format) %> -
> - <%= f.text_field :default_value, - id: "custom_fields_default_value_text", - for: "custom_fields_default_value_text", - container_class: "-wide" %> -
- <% end %> - <% if @custom_field.new_record? || @custom_field.field_format == 'bool' %> -
> - <%= f.check_box :default_value, - id: "custom_fields_default_value_bool", - for: "custom_fields_default_value_bool" %> -
- <% end %> - <% if @custom_field.new_record? || @custom_field.field_format == 'text' %> -
> - <%= f.text_area :default_value, - id: "custom_fields_default_value_longtext", - for: "custom_fields_default_value_longtext", - cols: 100, - rows: 20, - class: "wiki-edit", - macros: "none", - with_text_formatting: true %> -
- <% end %> <%= call_hook(:view_custom_fields_form_upper_box, custom_field: @custom_field, form: f) %>
-
- <% case @custom_field.class.name %> +
+ <% case @custom_field.type %> <% when "WorkPackageCustomField" %> -
- <%= f.check_box :is_required %> -
-

<%= t("custom_fields.instructions.is_required.all") %>

-
-
-
- <%= f.check_box :is_for_all %> -
-

<%= t("custom_fields.instructions.is_for_all.all") %>

-
-
-
- <%= f.check_box :is_filter %> -
-

<%= t("custom_fields.instructions.is_filter.all") %>

-
-
-
> - <%= f.check_box :searchable %> -
-

<%= t("custom_fields.instructions.searchable.all") %>

-
-
-
> - <%= f.check_box :content_right_to_left %> -
+ <%= + render( + Primer::Forms::FormList.new( + CustomFields::Details::RequiredForm.new(f), + CustomFields::Details::WorkPackageCustomFieldForm.new(f), + CustomFields::Details::SearchableForm.new(f), + CustomFields::Details::RightToLeftForm.new(f) + ) + ) + %> <% when "UserCustomField" %> -
- <%= f.check_box :is_required %> -
-

<%= t("custom_fields.instructions.is_required.all") %>

-
-
-
- <%= f.check_box :admin_only %> -
-

<%= t("custom_fields.instructions.admin_only.all") %>

-
-
-
- <%= f.check_box :editable %> -
-

<%= t("custom_fields.instructions.editable.all") %>

-
-
+ <%= + render( + Primer::Forms::FormList.new( + CustomFields::Details::RequiredForm.new(f), + CustomFields::Details::UserCustomFieldForm.new(f) + ) + ) + %> <% when "ProjectCustomField" %> -
- <%= f.check_box :is_required %> -
-

<%= t("custom_fields.instructions.is_required.project") %>

-
-
-
- <%= f.check_box :is_for_all %> -
-

<%= t("custom_fields.instructions.is_for_all.project") %>

-
-
-
- <%= f.check_box :admin_only %> -
-

<%= t("custom_fields.instructions.admin_only.project") %>

-
-
-
> - <%= f.check_box :searchable %> -
-

<%= t("custom_fields.instructions.searchable.project") %>

-
-
- <% when "TimeEntryCustomField" %> -
- <%= f.check_box :is_required %> -
-

<%= t("custom_fields.instructions.is_required.all") %>

-
-
+ <%= + render( + Primer::Forms::FormList.new( + CustomFields::Details::RequiredForm.new(f, for_project: true), + CustomFields::Details::AdminOnlyForm.new(f), + CustomFields::Details::SearchableForm.new(f, for_project: true) + ) + ) + %> <% else %> -
- <%= f.check_box :is_required %> -
-

<%= t("custom_fields.instructions.is_required.all") %>

-
-
+ <%= + render( + Primer::Forms::FormList.new( + CustomFields::Details::RequiredForm.new(f) + ) + ) + %> <% end %> + <%= call_hook(:"view_custom_fields_form_#{@custom_field.type.to_s.underscore}", custom_field: @custom_field, form: f) %>
diff --git a/app/views/custom_fields/edit.html.erb b/app/views/custom_fields/edit.html.erb index 937e22cd26d6..4a2623545d0f 100644 --- a/app/views/custom_fields/edit.html.erb +++ b/app/views/custom_fields/edit.html.erb @@ -37,14 +37,18 @@ See COPYRIGHT and LICENSE files for more details. <%= error_messages_for "custom_field" %> <% content_controller "admin--custom-fields", - "admin--custom-fields-format-config-value": OpenProject::CustomFieldFormatDependent.stimulus_config, - "admin--custom-fields-format-value": @custom_field.field_format %> - - <%= labelled_tabular_form_for @custom_field, - as: :custom_field, - url: custom_field_path(@custom_field), - html: { method: :put, id: "custom_field_form" } do |f| %> - <%= render partial: "form", locals: { f: f } %> - <%= styled_button_tag t(:button_save), class: "-primary -with-icon icon-checkmark" %> + "admin--custom-fields-format-value": @custom_field.field_format, + "admin--custom-fields-item-count-value": @custom_field.custom_options.size %> + + <%= + settings_primer_form_with( + model: @custom_field, + scope: :custom_field, + url: custom_field_path(@custom_field), + html: { id: "custom_field_form" } + ) do |f| + %> + <%= render partial: "form", locals: { f: } %> + <%= render CustomFields::Save.new(f) %> <% end %> <% end %> diff --git a/app/views/custom_fields/new.html.erb b/app/views/custom_fields/new.html.erb index feb38394b5c2..74292701befb 100644 --- a/app/views/custom_fields/new.html.erb +++ b/app/views/custom_fields/new.html.erb @@ -48,20 +48,20 @@ See COPYRIGHT and LICENSE files for more details. <%= error_messages_for "custom_field" %> <% content_controller "admin--custom-fields", - "admin--custom-fields-format-config-value": OpenProject::CustomFieldFormatDependent.stimulus_config, "admin--custom-fields-format-value": @custom_field.field_format, - "admin--custom-fields-hierarchy-enabled-value": EnterpriseToken.allows_to?(:custom_field_hierarchies) %> + "admin--custom-fields-hierarchy-enabled-value": EnterpriseToken.allows_to?(:custom_field_hierarchies), + "admin--custom-fields-item-count-value": @custom_field.custom_options.size %> - <%= labelled_tabular_form_for @custom_field, - as: :custom_field, - url: custom_fields_path, - html: { id: "custom_field_form", class: "-wide-labels" } do |f| %> - <%= render partial: "form", locals: { f: f } %> + <%= + settings_primer_form_with( + model: @custom_field, + scope: :custom_field, + url: custom_fields_path, + html: { id: "custom_field_form" } + ) do |f| + %> + <%= render partial: "form", locals: { f: } %> <%= hidden_field_tag "type", @custom_field.type %> - <%= styled_button_tag t(:button_save), - class: "-primary -with-icon icon-checkmark", - data: { - "admin--custom-fields-target": "submitButton" - } %> + <%= render CustomFields::Save.new(f, data: { admin__custom_fields_target: "submitButton" }) %> <% end %> <% end %> diff --git a/frontend/src/stimulus/controllers/dynamic/admin/custom-fields.controller.ts b/frontend/src/stimulus/controllers/dynamic/admin/custom-fields.controller.ts index b810e97c39ad..4b6c364ac0e2 100644 --- a/frontend/src/stimulus/controllers/dynamic/admin/custom-fields.controller.ts +++ b/frontend/src/stimulus/controllers/dynamic/admin/custom-fields.controller.ts @@ -37,30 +37,21 @@ export default class CustomFieldsController extends Controller { 'dragContainer', 'submitButton', + 'template', + 'table', 'customOptionDefaults', 'customOptionRow', - 'allowNonOpenVersions', - 'defaultBool', - 'defaultLongText', - 'defaultText', - 'length', - 'multiSelect', - 'possibleValues', - 'regexp', - 'searchable', - 'textOrientation', - 'enterpriseBanner', ]; static values = { - formatConfig: Array, + itemCount: Number, hierarchyEnabled: Boolean, format: String, }; - declare readonly formatConfigValue:[string, string, string[]][]; + declare itemCountValue:number; declare readonly formatValue:string; declare readonly hierarchyEnabledValue:boolean; @@ -70,22 +61,16 @@ export default class CustomFieldsController extends Controller { declare readonly submitButtonTarget:HTMLButtonElement; declare readonly hasSubmitButtonTarget:boolean; - declare readonly customOptionDefaultsTargets:HTMLInputElement[]; - declare readonly customOptionRowTargets:HTMLTableRowElement[]; - - declare readonly allowNonOpenVersionsTargets:HTMLElement[]; - declare readonly defaultBoolTargets:HTMLElement[]; - declare readonly defaultLongTextTargets:HTMLElement[]; - declare readonly defaultTextTargets:HTMLElement[]; - declare readonly lengthTargets:HTMLElement[]; - declare readonly multiSelectTargets:HTMLElement[]; - declare readonly possibleValuesTargets:HTMLElement[]; - declare readonly regexpTargets:HTMLElement[]; - declare readonly searchableTargets:HTMLInputElement[]; - declare readonly textOrientationTargets:HTMLElement[]; + declare readonly templateTarget:HTMLElement; + declare readonly tableTarget:HTMLTableElement; + declare readonly customOptionDefaultsTargets:HTMLInputElement[]; declare readonly enterpriseBannerTarget:HTMLElement; + get customOptionRows() { + return [...this.tableTarget.tBodies[0].rows]; + } + connect() { if (this.hasDragContainerTarget) { this.setupDragAndDrop(); @@ -96,9 +81,9 @@ export default class CustomFieldsController extends Controller { moveRowUp(event:{ target:HTMLElement }) { const row = event.target.closest('tr')!; - const idx = this.customOptionRowTargets.indexOf(row); + const idx = this.customOptionRows.indexOf(row); if (idx > 0) { - this.customOptionRowTargets[idx - 1].before(row); + this.customOptionRows[idx - 1].before(row); } return false; @@ -106,9 +91,10 @@ export default class CustomFieldsController extends Controller { moveRowDown(event:{ target:HTMLElement }) { const row = event.target.closest('tr')!; - const idx = this.customOptionRowTargets.indexOf(row); - if (idx < this.customOptionRowTargets.length - 1) { - this.customOptionRowTargets[idx + 1].after(row); + const idx = this.customOptionRows.indexOf(row); + + if (idx < this.customOptionRows.length - 1) { + this.customOptionRows[idx + 1].after(row); } return false; @@ -116,7 +102,7 @@ export default class CustomFieldsController extends Controller { moveRowToTheTop(event:{ target:HTMLElement }) { const row = event.target.closest('tr')!; - const first = this.customOptionRowTargets[0]; + const first = this.customOptionRows[0]; if (first && first !== row) { first.before(row); @@ -127,7 +113,7 @@ export default class CustomFieldsController extends Controller { moveRowToTheBottom(event:{ target:HTMLElement }) { const row = event.target.closest('tr')!; - const last = this.customOptionRowTargets[this.customOptionRowTargets.length - 1]; + const last = this.customOptionRows[this.customOptionRows.length - 1]; if (last && last !== row) { last.after(row); @@ -137,59 +123,39 @@ export default class CustomFieldsController extends Controller { } removeOption(event:MouseEvent) { - const self = event.target as HTMLAnchorElement; - if (self.href === '#' || self.href.endsWith('/0')) { - const row = self.closest('tr'); - - if (row && this.customOptionRowTargets.length > 1) { - row.remove(); - } + const self = event.target as HTMLButtonElement; + const row = self.closest('tr'); - event.preventDefault(); - event.stopImmediatePropagation(); + if (row && this.customOptionRows.length > 1) { + row.remove(); } + + event.preventDefault(); + event.stopImmediatePropagation(); + return true; // send off deletion } addOption() { - const count = this.customOptionRowTargets.length; - const last = this.customOptionRowTargets[count - 1]; - const dup = last.cloneNode(true) as HTMLElement; + const newRow = this.templateTarget.cloneNode(true); + this.tableTarget.append(newRow); - const input = dup.querySelector('.custom-option-value input') as HTMLInputElement; + const addedRow = this.tableTarget.lastChild as HTMLElement; + addedRow.outerHTML = addedRow.outerHTML.replace(/INDEX/g, this.itemCountValue.toString()); - input.setAttribute('name', `custom_field[custom_options_attributes][${count}][value]`); - input.setAttribute('id', `custom_field_custom_options_attributes_${count}_value`); - input.value = ''; - - dup - .querySelector('.custom-option-id') - ?.remove(); - - const defaultValueCheckbox = dup.querySelector('input[type="checkbox"]') as HTMLInputElement; - const defaultValueHidden = dup.querySelector('input[type="hidden"]') as HTMLInputElement; - - defaultValueHidden.setAttribute('name', `custom_field[custom_options_attributes][${count}][default_value]`); - defaultValueHidden.removeAttribute('id'); - defaultValueCheckbox.setAttribute('name', `custom_field[custom_options_attributes][${count}][default_value]`); - defaultValueCheckbox.setAttribute('id', `custom_field_custom_options_attributes_${count}_default_value`); - defaultValueCheckbox.checked = false; - - last.insertAdjacentElement('afterend', dup); - - return false; + this.itemCountValue += 1; } uncheckOtherDefaults(event:{ target:HTMLElement }) { const cb = event.target as HTMLInputElement; if (cb.checked) { - const multi = this.multiSelectTargets[0] as HTMLInputElement|undefined; + const multi = undefined; // FIXME this.multiSelectTargets[0] as HTMLInputElement|undefined; - if (multi?.checked === false) { - this.customOptionDefaultsTargets.forEach((el) => (el.checked = false)); - cb.checked = true; - } + // if (multi?.checked === false) { + // this.customOptionDefaultsTargets.forEach((el) => (el.checked = false)); + // cb.checked = true; + // } } } @@ -252,13 +218,6 @@ export default class CustomFieldsController extends Controller { this.submitButtonTarget.disabled = format === 'hierarchy' && !this.hierarchyEnabledValue; } - this.formatConfigValue.forEach(([targetsName, operator, formats]) => { - const active = operator === 'only' ? formats.includes(format) : !formats.includes(format); - const targets = this[`${targetsName}Targets` as keyof typeof this] as HTMLElement[]; - if (targets) { - this.setActive(targets, active); - } - }); } } diff --git a/lib/open_project/custom_field_format_dependent.rb b/lib/open_project/custom_field_format_dependent.rb index 9a39e7de624e..1ba4ff5a6d99 100644 --- a/lib/open_project/custom_field_format_dependent.rb +++ b/lib/open_project/custom_field_format_dependent.rb @@ -29,42 +29,23 @@ module OpenProject class CustomFieldFormatDependent CONFIG = { - allowNonOpenVersions: [:only, %w[version]], - defaultBool: [:only, %w[bool]], - defaultLongText: [:only, %w[text]], - defaultText: [:except, %w[list bool date text user version hierarchy calculated_value]], - length: [:except, %w[list bool date user version link hierarchy calculated_value]], - multiSelect: [:only, %w[list user version hierarchy]], possibleValues: [:only, %w[list]], - regexp: [:except, %w[list bool date user version hierarchy calculated_value]], formula: [:only, %w[calculated_value]], - searchable: [:except, %w[bool date float int user version hierarchy calculated_value]], - textOrientation: [:only, %w[text]], enterpriseBanner: [:only, %w[hierarchy]] }.freeze - def self.stimulus_config - CONFIG - .map { |target_name, (operator, formats)| [target_name, operator, formats] }.to_json - end - attr_reader :format def initialize(format) @format = format end - def attributes(target_name) + def visible?(target_name) operator, formats = CONFIG[target_name.to_sym] fail ArgumentError, "Unknown target name #{target_name}" unless formats - visible = operator == :only ? format.in?(formats) : !format.in?(formats) - - ApplicationController.helpers.tag.attributes( - data: { "admin--custom-fields-target": target_name }, - hidden: !visible - ) + operator == :only ? format.in?(formats) : !format.in?(formats) end end end diff --git a/spec/components/custom_fields/custom_options/row_component_spec.rb b/spec/components/custom_fields/custom_options/row_component_spec.rb new file mode 100644 index 000000000000..f424bb977b3c --- /dev/null +++ b/spec/components/custom_fields/custom_options/row_component_spec.rb @@ -0,0 +1,112 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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. +#++ + +require "rails_helper" + +RSpec.describe CustomFields::CustomOptions::RowComponent, type: :component do + let(:custom_field) { create(:custom_field) } + let(:table) do + instance_double( + CustomFields::CustomOptions::TableComponent, + columns: %i[value default_value], + custom_field: + ) + end + + subject(:rendered_component) do + render_in_view_context( + described_class, + custom_option, + custom_field, + table, + self + ) do |described_class, custom_option, custom_field, table, spec_context| + primer_form_with(url: "/foo", model: custom_field) do |f| + spec_context.allow(table).to spec_context.receive(:form).and_return(f) + + render(described_class.new(row: custom_option, row_counter: 0, table:)) + end + end + + rendered_content # we want a string rather Nokogiri::HTML5.fragment to workaround it stripping + end + + context "with new custom option" do + let(:custom_option) { build(:custom_option, custom_field:) } + + it "renders row" do + expect(rendered_component).to have_element :tr + end + + it "renders cells" do + expect(rendered_component).to have_element :td, count: 3 + end + + it "renders 'Value' input" do + expect(rendered_component).to have_field "Value" do |field| + expect(field["name"]).to eq "custom_field[custom_options_attributes][0][value]" + expect(field["id"]).to eq "custom_field_custom_options_attributes_0_value" + end + end + + it "renders 'Default' input" do + expect(rendered_component).to have_field "Default" do |field| + expect(field["name"]).to eq "custom_field[custom_options_attributes][0][default_value]" + expect(field["id"]).to eq "custom_field_custom_options_attributes_0_default_value" + end + end + end + + context "with existing custom option" do + let(:custom_option) { create(:custom_option, custom_field:) } + + it "renders row" do + expect(rendered_component).to have_element :tr + end + + it "renders cells" do + expect(rendered_component).to have_element :td, count: 3 + end + + it "renders 'Value' input" do + expect(rendered_component).to have_field "Value" do |field| + expect(field["name"]).to eq "custom_field[custom_options_attributes][#{custom_option.id}][value]" + expect(field["id"]).to eq "custom_field_custom_options_attributes_#{custom_option.id}_value" + end + end + + it "renders 'Default' input" do + expect(rendered_component).to have_field "Default" do |select| + expect(select["name"]).to eq "custom_field[custom_options_attributes][#{custom_option.id}][default_value]" + expect(select["id"]).to eq "custom_field_custom_options_attributes_#{custom_option.id}_default_value" + end + end + end +end diff --git a/spec/components/custom_fields/custom_options/table_component_spec.rb b/spec/components/custom_fields/custom_options/table_component_spec.rb new file mode 100644 index 000000000000..1b743db66676 --- /dev/null +++ b/spec/components/custom_fields/custom_options/table_component_spec.rb @@ -0,0 +1,65 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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. +#++ + +require "rails_helper" + +RSpec.describe CustomFields::CustomOptions::TableComponent, type: :component do + def render_component(...) + render_inline(described_class.new(...)) + end + + let(:form) { instance_double(Primer::Forms::Builder, fields_for: "") } + let(:custom_field) { create(:custom_field) } + + subject(:rendered_component) do + render_component(rows: custom_options, form:, custom_field:) + end + + context "with no custom options" do + let(:custom_options) { create_list(:custom_option, 0, custom_field:) } + + it "renders headers" do + expect(rendered_component).to have_css "th .generic-table--sort-header", text: "Value" + expect(rendered_component).to have_css "th .generic-table--sort-header", text: "Default" + end + + it "renders 1 row" do + expect(rendered_component).to have_css "tbody tr", count: 1 + end + end + + context "with custom options" do + let(:custom_options) { create_list(:custom_option, 2, custom_field:) } + + it "renders 2 rows" do + expect(rendered_component).to have_css "tbody tr", count: 2 + end + end +end diff --git a/spec/components/custom_fields/custom_options_component_spec.rb b/spec/components/custom_fields/custom_options_component_spec.rb new file mode 100644 index 000000000000..a91c3491baf7 --- /dev/null +++ b/spec/components/custom_fields/custom_options_component_spec.rb @@ -0,0 +1,68 @@ +# frozen_string_literal: true + +#-- copyright +# OpenProject is an open source project management software. +# Copyright (C) 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. +#++ + +require "rails_helper" + +RSpec.describe CustomFields::CustomOptionsComponent, type: :component do + def render_component(...) + render_inline(described_class.new(...)) + end + + let(:custom_field) { create(:custom_field) } + let(:form) { instance_double(Primer::Forms::Builder, fields_for: "") } + + subject(:rendered_component) do + render_component(custom_field: custom_field, form:) + end + + before do + custom_field.reload + end + + context "with no custom options" do + let!(:custom_options) { create_list(:custom_option, 0, custom_field:) } + + it "renders table" do + expect(rendered_component).to have_element :table do |table| + expect(table["data-admin--custom-fields-target"]).to eq "table" + end + end + end + + context "with custom options" do + let!(:custom_options) { create_list(:custom_option, 2, custom_field:) } + + it "renders table" do + expect(rendered_component).to have_element :table do |table| + expect(table["data-admin--custom-fields-target"]).to eq "table" + end + end + end +end diff --git a/spec/lib/open_project/custom_field_format_dependent_spec.rb b/spec/lib/open_project/custom_field_format_dependent_spec.rb deleted file mode 100644 index 79ff275d8a9f..000000000000 --- a/spec/lib/open_project/custom_field_format_dependent_spec.rb +++ /dev/null @@ -1,80 +0,0 @@ -# frozen_string_literal: true - -#-- copyright -# OpenProject is an open source project management software. -# Copyright (C) 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. -#++ - -require "spec_helper" - -RSpec.describe OpenProject::CustomFieldFormatDependent do - describe ".stimulus_config" do - it "returns a json with expected structure" do - expect(JSON.parse(described_class.stimulus_config)).to all match([be_a(String), be_a(String), all(be_a(String))]) - end - end - - describe "#attributes" do - let(:instance) { described_class.new(format) } - let(:format) { "string" } - - subject(:call) { instance.attributes(target_name) } - - context "for targets using operator only" do - let(:target_name) { :defaultLongText } - - context "for matching format" do - let(:format) { "text" } - - it { is_expected.to be_html_safe & eq('data-admin--custom-fields-target="defaultLongText"') } - end - - context "for non matching format" do - it { is_expected.to be_html_safe & eq('data-admin--custom-fields-target="defaultLongText" hidden="hidden"') } - end - end - - context "for targets using operator except" do - let(:target_name) { :defaultText } - - context "for matching format" do - let(:format) { "text" } - - it { is_expected.to be_html_safe & eq('data-admin--custom-fields-target="defaultText" hidden="hidden"') } - end - - context "for non matching format" do - it { is_expected.to be_html_safe & eq('data-admin--custom-fields-target="defaultText"') } - end - end - - context "for unknown target" do - let(:target_name) { :foo } - - it { expect { call }.to raise_error(ArgumentError) } - end - end -end