Skip to content

Commit c7afb49

Browse files
committed
Get inplaceEditField for customField dynamically by the format instead of registring them all directly
1 parent adb88c9 commit c7afb49

File tree

11 files changed

+60
-80
lines changed

11 files changed

+60
-80
lines changed

app/components/open_project/common/inplace_edit_field_component.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,11 @@ def initialize(model:,
6060
end
6161

6262
def field_class
63-
OpenProject::InplaceEdit::FieldRegistry.fetch(attribute)
63+
if custom_field?
64+
OpenProject::InplaceEdit::FieldRegistry.fetch_for_custom_field_format(custom_field&.field_format)
65+
else
66+
OpenProject::InplaceEdit::FieldRegistry.fetch(attribute)
67+
end
6468
end
6569

6670
def edit_field_component(form)
@@ -212,8 +216,7 @@ def required?
212216
# For custom fields, check the is_required attribute
213217
custom_field&.is_required || false
214218
else
215-
# For regular model attributes, check ActiveRecord validations
216-
model.class.validators_on(attribute).any?(ActiveRecord::Validations::PresenceValidator)
219+
false
217220
end
218221
end
219222

app/components/open_project/common/inplace_edit_fields/display_fields/calculated_value_input_component.rb

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@ class CalculatedValueInputComponent < DisplayFieldComponent
3838

3939
attr_reader :model, :attribute
4040

41+
# If the writable attribute is not explicitly listed as an argument,
42+
# it will be interpreted as one of the system_arguments and thus overwrite the `writable: false`
43+
# rubocop:disable Lint/UnusedMethodArgument
4144
def initialize(model:, attribute:, writable: nil, truncated: false, has_comment: false, show_comment: false,
4245
**system_arguments)
4346
super(model:, attribute:, writable: false, truncated:, has_comment:, show_comment:, **system_arguments)
4447
end
48+
# rubocop:enable Lint/UnusedMethodArgument
4549

4650
def render_calculation_error
4751
error = custom_field&.first_calculation_error(model)

app/components/open_project/common/inplace_edit_fields/display_fields/display_fields_component.sass

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
padding: var(--base-size-4) var(--base-size-8)
44
border: 1px solid transparent
55
border-radius: var(--borderRadius-medium)
6+
@include text-shortener(false)
67

78
&:hover, &:focus
89
border-color: var(--borderColor-default)

app/components/open_project/common/inplace_edit_fields/display_fields/link_input_component.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,7 @@ def render_link(href)
5151
link = Addressable::URI.parse(href)
5252
return href unless link
5353

54-
target = link.host == Setting.host_without_protocol ? "_top" : "_blank"
55-
render(Primer::Beta::Link.new(href:, rel: "noopener noreferrer", target:)) do
54+
render(Primer::Beta::Link.new(href:, rel: "noopener noreferrer")) do
5655
href
5756
end
5857
end

app/controllers/inplace_edit_fields_controller.rb

Lines changed: 24 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -46,27 +46,8 @@ def edit
4646

4747
def update
4848
success = invoke_update_handler
49-
50-
if success
51-
render_success_flash_message_via_turbo_stream(
52-
message: I18n.t(:notice_successful_update)
53-
)
54-
close_dialog_via_turbo_stream(dialog_id) if dialog_id
55-
refresh_calculated_dependents
56-
end
57-
58-
if !success && dialog_id
59-
replace_via_turbo_stream(
60-
component: dialog_field_component,
61-
status: :unprocessable_entity
62-
)
63-
else
64-
replace_via_turbo_stream(
65-
component: component(enforce_edit_mode: !success),
66-
status: success ? :ok : :unprocessable_entity
67-
)
68-
end
69-
49+
handle_update_success if success
50+
replace_field_component(success)
7051
respond_with_turbo_streams
7152
rescue ArgumentError
7253
head :not_found
@@ -96,6 +77,28 @@ def invoke_update_handler
9677
handler.call(model: @model, params: permitted_params, user: current_user)
9778
end
9879

80+
def handle_update_success
81+
render_success_flash_message_via_turbo_stream(
82+
message: I18n.t(:notice_successful_update)
83+
)
84+
close_dialog_via_turbo_stream(dialog_id) if dialog_id
85+
refresh_calculated_dependents
86+
end
87+
88+
def replace_field_component(success)
89+
if !success && dialog_id
90+
replace_via_turbo_stream(
91+
component: dialog_field_component,
92+
status: :unprocessable_entity
93+
)
94+
else
95+
replace_via_turbo_stream(
96+
component: component(enforce_edit_mode: !success),
97+
status: success ? :ok : :unprocessable_entity
98+
)
99+
end
100+
end
101+
99102
def find_model
100103
model_class = resolve_model_class(params[:model])
101104
@model = model_class.visible.find(params[:id])

app/models/custom_field.rb

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ class CustomField < ApplicationRecord
8888
validates :has_comment, absence: true, unless: :can_have_comment?
8989

9090
before_validation :check_searchability
91-
after_create :register_inplace_edit_component
91+
9292
after_destroy :destroy_help_text
9393

9494
# make sure int, float, date, and bool are not searchable
@@ -482,8 +482,4 @@ def destroy_help_text
482482
.where(attribute_name:)
483483
.destroy_all
484484
end
485-
486-
def register_inplace_edit_component
487-
OpenProject::InplaceEdit::FieldRegistry.register_custom_field(id, field_format)
488-
end
489485
end

config/initializers/inplace_edit_fields.rb

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,6 @@
5353

5454
OpenProject::InplaceEdit::FieldRegistry.register_custom_field_format_mappings(custom_field_format_mappings)
5555

56-
if CustomField.table_exists?
57-
CustomField.pluck(:id, :field_format).each do |id, field_format|
58-
OpenProject::InplaceEdit::FieldRegistry.register_custom_field(id, field_format)
59-
end
60-
end
61-
6256
# Register the update handler per model
6357
OpenProject::InplaceEdit::UpdateRegistry.register(Project,
6458
handler: OpenProject::InplaceEdit::Handlers::ProjectUpdate,

lib/open_project/inplace_edit/field_registry.rb

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -44,21 +44,22 @@ def register_custom_field_format_mappings(mappings)
4444
@custom_field_format_mappings = mappings
4545
end
4646

47-
def register_custom_field(id, field_format)
48-
component = @custom_field_format_mappings[field_format]
49-
register("custom_field_#{id}", component) if component
50-
end
51-
5247
def fetch(attribute_name)
5348
@registry.fetch(attribute_name.to_s) { Common::InplaceEditFields::TextInputComponent }
5449
end
5550

51+
def fetch_for_custom_field_format(field_format)
52+
return Common::InplaceEditFields::TextInputComponent if field_format.nil?
53+
54+
@custom_field_format_mappings.fetch(field_format.to_s) { Common::InplaceEditFields::TextInputComponent }
55+
end
56+
5657
@default = new
5758

5859
class << self
5960
attr_reader :default
6061

61-
delegate :register, :fetch, :register_custom_field_format_mappings, :register_custom_field, to: :@default
62+
delegate :register, :fetch, :fetch_for_custom_field_format, :register_custom_field_format_mappings, to: :@default
6263
end
6364
end
6465
end

spec/features/projects/project_custom_fields/overview_page/attribute_help_texts_spec.rb

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,11 @@
4646
context "without attribute help texts defined" do
4747
it "shows field labels without help text link" do
4848
input_fields.each do |custom_field|
49-
field = overview_page.open_inplace_edit_field_for_custom_field(custom_field)
49+
field = if custom_field == text_project_custom_field
50+
overview_page.open_modal_for_custom_field(custom_field)
51+
else
52+
overview_page.open_inplace_edit_field_for_custom_field(custom_field)
53+
end
5054
field.expect_field_label_without_help_text custom_field.name
5155
field.close
5256
end

spec/lib/open_project/inplace_edit/field_registry_spec.rb

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -63,33 +63,32 @@
6363
end
6464

6565
describe "#register_custom_field_format_mappings" do
66-
it "stores format-to-component mappings used by register_custom_field" do
66+
it "stores format-to-component mappings used by fetch_for_custom_field_format" do
6767
text_component = Class.new
6868
registry.register_custom_field_format_mappings("text" => text_component)
6969

70-
registry.register_custom_field(42, "text")
71-
72-
expect(registry.fetch("custom_field_42")).to eq(text_component)
70+
expect(registry.fetch_for_custom_field_format("text")).to eq(text_component)
7371
end
7472
end
7573

76-
describe "#register_custom_field" do
74+
describe "#fetch_for_custom_field_format" do
7775
let(:text_component) { Class.new }
7876

7977
before do
8078
registry.register_custom_field_format_mappings("text" => text_component)
8179
end
8280

83-
it "registers the correct component for the given field format" do
84-
registry.register_custom_field(1, "text")
85-
86-
expect(registry.fetch("custom_field_1")).to eq(text_component)
81+
it "returns the correct component for the given field format" do
82+
expect(registry.fetch_for_custom_field_format("text")).to eq(text_component)
8783
end
8884

89-
it "does nothing when the format has no mapping" do
90-
registry.register_custom_field(2, "unknown_format")
85+
it "falls back to TextInputComponent when the format has no mapping" do
86+
expect(registry.fetch_for_custom_field_format("unknown_format"))
87+
.to eq(OpenProject::Common::InplaceEditFields::TextInputComponent)
88+
end
9189

92-
expect(registry.fetch("custom_field_2"))
90+
it "falls back to TextInputComponent when field_format is nil" do
91+
expect(registry.fetch_for_custom_field_format(nil))
9392
.to eq(OpenProject::Common::InplaceEditFields::TextInputComponent)
9493
end
9594
end

0 commit comments

Comments
 (0)