From 6866886bff1c39f1fff213444211badecd6e0b46 Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad Date: Wed, 13 May 2026 16:55:33 +0200 Subject: [PATCH 1/6] Show filed type beside its name --- .../group_attribute_row_component.html.erb | 7 ++++++- app/helpers/types_helper.rb | 14 +++++++++++++- app/models/type/attributes.rb | 3 ++- config/locales/en.yml | 1 + 4 files changed, 22 insertions(+), 3 deletions(-) diff --git a/app/components/work_package_types/form_configuration/group_attribute_row_component.html.erb b/app/components/work_package_types/form_configuration/group_attribute_row_component.html.erb index 8ad7d6a2a65a..d91d3641d0f1 100644 --- a/app/components/work_package_types/form_configuration/group_attribute_row_component.html.erb +++ b/app/components/work_package_types/form_configuration/group_attribute_row_component.html.erb @@ -10,9 +10,14 @@ ) ) end - left.with_column(flex: 1) do + left.with_column do render(Primer::Beta::Text.new) { @attribute[:translation] } end + if @attribute[:field_type].present? + left.with_column(ml: 2) do + render(Primer::Beta::Text.new(color: :muted, font_size: :small)) { @attribute[:field_type] } + end + end end row.with_column(classes: "hide-when-print type-form-configuration-page--actions") do diff --git a/app/helpers/types_helper.rb b/app/helpers/types_helper.rb index 9ade93941933..5a4f3a2865d8 100644 --- a/app/helpers/types_helper.rb +++ b/app/helpers/types_helper.rb @@ -150,7 +150,19 @@ def attr_form_map(key, represented) key:, is_cf: CustomField.custom_field_attribute?(key), is_required: represented[:required] && !represented[:has_default], - translation: Type.translated_attribute_name(key, represented) + translation: Type.translated_attribute_name(key, represented), + field_type: field_type_label(key, represented) } end + + def field_type_label(_key, represented) + if represented[:is_cf] + format = OpenProject::CustomFieldFormat.find_by(name: represented[:field_format]) + return "" if format.nil? + + format.label.is_a?(Proc) ? format.label.call : I18n.t(format.label) + else + I18n.t("types.edit.form_configuration.builtin_field") + end + end end diff --git a/app/models/type/attributes.rb b/app/models/type/attributes.rb index bc4e787a1f5a..3b40e88db6a7 100644 --- a/app/models/type/attributes.rb +++ b/app/models/type/attributes.rb @@ -153,7 +153,8 @@ def add_custom_fields_to_form_attributes(attributes) required: field.is_required, has_default: field.default_value.present?, is_cf: true, - display_name: field.name + display_name: field.name, + field_format: field.field_format } end end diff --git a/config/locales/en.yml b/config/locales/en.yml index 46c674d24539..65fcae4edd5e 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1435,6 +1435,7 @@ en: untitled_group: "Untitled group" reset_title: "Reset form configuration" confirm_reset: "Are you sure you want to reset the form configuration?" + builtin_field: "Builtin field" reset_description: > This will reset the attributes to their default group and disable ALL custom fields. projects: From e5dd4bd7df2c59f95eca2415611ddae0a2fdde02 Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad Date: Wed, 13 May 2026 17:01:44 +0200 Subject: [PATCH 2/6] Add feature spec --- .../features/types/form_configuration_spec.rb | 11 +++++++ spec/helpers/types_helper_spec.rb | 33 +++++++++++++++++++ 2 files changed, 44 insertions(+) diff --git a/spec/features/types/form_configuration_spec.rb b/spec/features/types/form_configuration_spec.rb index 749fa00768f9..c2086e8c94cb 100644 --- a/spec/features/types/form_configuration_spec.rb +++ b/spec/features/types/form_configuration_spec.rb @@ -250,6 +250,16 @@ def persisted_attribute_order(type, group_key) loading_indicator_saveguard end + it "shows field type labels beside attributes" do + # Built-in attributes show "Builtin field" + builtin_label = I18n.t("types.edit.form_configuration.builtin_field") + assignee_row = page.find('li[data-attr-key="assignee"]') + expect(assignee_row).to have_text(builtin_label) + + date_row = page.find('li[data-attr-key="date"]') + expect(date_row).to have_text(builtin_label) + end + it "removes a newly added unsaved custom group when canceling edit" do initial_order = form.group_order @@ -259,6 +269,7 @@ def persisted_attribute_order(type, group_key) expect(page.find_test_selector("type-form-configuration-group-name-input", wait: 10).value).to eq("") page.find_test_selector("type-form-configuration-group-cancel", wait: 10).click + expect(page).to have_no_test_selector("type-form-configuration-group-name-input") expect(form.group_order).to eq(initial_order) end diff --git a/spec/helpers/types_helper_spec.rb b/spec/helpers/types_helper_spec.rb index 90515dc03c08..8a876c38bb11 100644 --- a/spec/helpers/types_helper_spec.rb +++ b/spec/helpers/types_helper_spec.rb @@ -88,5 +88,38 @@ expect(subject.first[:key]).to eq :details end end + + describe ":field_type" do + before do + allow(type) + .to receive(:attribute_groups) + .and_return [Type::AttributeGroup.new(type, "group one", ["assignee"])] + end + + it "returns 'Builtin field' for built-in attributes" do + groups = helper.form_configuration_groups(type) + attribute = groups[:actives].first[:attributes].first + + expect(attribute[:field_type]).to eq I18n.t("types.edit.form_configuration.builtin_field") + end + + it "returns 'Builtin field' for inactive built-in attributes" do + groups = helper.form_configuration_groups(type) + inactive_builtin = groups[:inactives].find { |a| a[:key] == "date" } + + expect(inactive_builtin[:field_type]).to eq I18n.t("types.edit.form_configuration.builtin_field") + end + + context "with a custom field" do + let!(:custom_field) { create(:wp_custom_field, :string, name: "My CF") } + + it "returns the custom field format label" do + groups = helper.form_configuration_groups(type) + cf_attr = groups[:inactives].find { |a| a[:key] == custom_field.attribute_name } + + expect(cf_attr[:field_type]).to eq I18n.t(:label_string) + end + end + end end end From 281cda6396e2297d7c0633c70713319e99012427 Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad <62008897+bsatarnejad@users.noreply.github.com> Date: Wed, 13 May 2026 17:57:22 +0200 Subject: [PATCH 3/6] Add a comment for field_type_label --- app/helpers/types_helper.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/app/helpers/types_helper.rb b/app/helpers/types_helper.rb index 5a4f3a2865d8..fa67e53986c0 100644 --- a/app/helpers/types_helper.rb +++ b/app/helpers/types_helper.rb @@ -155,6 +155,9 @@ def attr_form_map(key, represented) } end + # Resolves the format label directly via OpenProject::CustomFieldFormat rather than + # using CustomFieldsHelper#label_for_custom_field_format, because the helper is not + # available in the controller context during Turbo Stream re-renders. def field_type_label(_key, represented) if represented[:is_cf] format = OpenProject::CustomFieldFormat.find_by(name: represented[:field_format]) From 13c6e234659167b1f9ba33bffb222781a459967e Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad <62008897+bsatarnejad@users.noreply.github.com> Date: Fri, 15 May 2026 10:33:52 +0200 Subject: [PATCH 4/6] Potential fix for pull request finding Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com> --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 65fcae4edd5e..37ce3b98946b 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -1435,7 +1435,7 @@ en: untitled_group: "Untitled group" reset_title: "Reset form configuration" confirm_reset: "Are you sure you want to reset the form configuration?" - builtin_field: "Builtin field" + builtin_field: "Built-in field" reset_description: > This will reset the attributes to their default group and disable ALL custom fields. projects: From 5c1b8ea986d05528a046161e838c459c3adc848c Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad Date: Fri, 15 May 2026 11:49:10 +0200 Subject: [PATCH 5/6] Add custom field type label assertion to feature spec --- spec/features/types/form_configuration_spec.rb | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/spec/features/types/form_configuration_spec.rb b/spec/features/types/form_configuration_spec.rb index c2086e8c94cb..651a9d30c1bb 100644 --- a/spec/features/types/form_configuration_spec.rb +++ b/spec/features/types/form_configuration_spec.rb @@ -258,6 +258,13 @@ def persisted_attribute_order(type, group_key) date_row = page.find('li[data-attr-key="date"]') expect(date_row).to have_text(builtin_label) + + # Custom fields show their format label + custom_field = create(:issue_custom_field, :integer, name: "MyNumber") + visit edit_type_form_configuration_path(type) + + cf_row = page.find("li[data-attr-key='#{custom_field.attribute_name}']") + expect(cf_row).to have_text(I18n.t(:label_integer)) end it "removes a newly added unsaved custom group when canceling edit" do From dfe9c45d749f9089390e86ea12ae5241136d9834 Mon Sep 17 00:00:00 2001 From: Behrokh Satarnejad Date: Fri, 15 May 2026 14:25:00 +0200 Subject: [PATCH 6/6] Move custom field to active group before asserting type label --- spec/features/types/form_configuration_spec.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/spec/features/types/form_configuration_spec.rb b/spec/features/types/form_configuration_spec.rb index 651a9d30c1bb..760c46165b47 100644 --- a/spec/features/types/form_configuration_spec.rb +++ b/spec/features/types/form_configuration_spec.rb @@ -263,6 +263,7 @@ def persisted_attribute_order(type, group_key) custom_field = create(:issue_custom_field, :integer, name: "MyNumber") visit edit_type_form_configuration_path(type) + form.move_to(custom_field.attribute_name, "Details") cf_row = page.find("li[data-attr-key='#{custom_field.attribute_name}']") expect(cf_row).to have_text(I18n.t(:label_integer)) end