From b23cf41d865aa611bbce75df674a47be6b851514 Mon Sep 17 00:00:00 2001 From: martin Date: Fri, 6 Jun 2025 14:25:10 +0200 Subject: [PATCH 1/4] describe easy form and new design implementation --- docs/Backend_tutorials/features/easy_form.md | 114 +++++++++++++++++++ toc.json | 5 + 2 files changed, 119 insertions(+) create mode 100644 docs/Backend_tutorials/features/easy_form.md diff --git a/docs/Backend_tutorials/features/easy_form.md b/docs/Backend_tutorials/features/easy_form.md new file mode 100644 index 0000000..6e15275 --- /dev/null +++ b/docs/Backend_tutorials/features/easy_form.md @@ -0,0 +1,114 @@ +# Easy Form + +Warning: V15 required! + +Easy Form is a new approach for building forms in ERB templates for application version V15 and higher. +It aims to simplify form construction, reduce repetitive code, reduce level of customization +and encourage consistent structure and styling across views accordingly to design system. + +Implementation is included as helper module `easy_form_helper.rb` within `EasyExtensions`. +It contains two methods `easy_form_for` and `easy_form_tag`, which are used to create forms in views. + +Both methods use `EasyExtensions::EasyFormBuilder` as a form builder to provide implementation of individual components. + +## easy_form_for +`easy_form_for` is used to create forms for specific model. Mandatory argument for this method is `model` instance. +Additional optional arguments are: +- `local` - tells Rails whether the form should behave as a regular HTML form or a JavaScript-enhanced remote form, +- `url` - custom url for form submission, if not specified, it will use the default URL based on the model's routing, +- `method` - HTTP method for form submission, +- `format` - format of response, +- `html` - additional HTML options. + +```erb title="example of method usage" +<%= easy_form_for(model: @my_model) do |f| %> + <%= f.text_field :name %> + <%= f.submit "Save" %> +<% end %> +``` + +## easy_form_tag +`easy_form_tag` is used to create forms without a specific model. +It is useful for forms that do not correspond to a single model or when you want to submit data that does not directly map to a model. +Mandatory arguments are: +- `scope` - scope for the form, which is used to generate unique IDs and names for form fields, +- `url` - URL for form submission, +Optional arguments are: +- `method` - HTTP method for form submission, default is `:post`, +- `local` - whether the form should behave as a regular HTML form or a JavaScript-enhanced remote form, +- `format` - format of response, +- `html` - additional HTML options. + +```erb title="example of method usage" +<%= easy_form_tag(scope: "my_form", url: my_custom_path) do |f| %> + <%= f.text_field :name %> + <%= f.submit "Submit" %> +<% end %> +``` + +## EasyFormBuilder +`EasyFormBuilder` is a custom form builder that inherits from `ActionView::Helpers::FormBuilder` +and provides interface for creating form fields with consistent styling and structure. +Source code is located in `app/utils/easy_extensions/easy_form_builder.rb`. + +Builder methods either implements required html content or calls component to render it. +Html structure, behaviour and usage of each method for individual form field/component are described +in [Easy Storybook](https://es.easyproject.com/easy_storybook). + +## Components +To make form construction more modular and expressive, Easy Form supports the use of form components. +A form component is a plain Ruby class responsible for rendering a specific part of a form — such as an input field, field_set, etc. +Each component follows consistent interface, making it easy to integrate and extend. + +Base interface provides class and instance method for rendering `render`. +Instance method is responsible for rendering component content and accepts block as optional argument. +Class method accepts any named arguments and block as well. Passes named arguments to instance constructor. +With initialized instance, it calls `render` with (optional) block. + +```ruby title="base component interface" lineNumbers +module EasyFormComponents + class Base + include ActionView::Helpers::TagHelper + include ActionView::Context + include Redmine::I18n + + def self.render(**, &) + new(**).render(&) + end + + def render(&_block) + raise NotImplementedError + end + + end +end +``` + +```Ruby title="example of component" lineNumbers +module EasyFormComponents + class TextField < Base + + # @param [EasyExtensions::EasyFormBuilder] builder + # @param [Symbol] field + # @param [Hash] options + def initialize(builder:, field:, options: {}) + @builder = builder + @field = field + @options = options + end + + def render + builder.text_field(field, options) + end + + private + + attr_reader :builder, :field, :options + end +end +``` + + + + + diff --git a/toc.json b/toc.json index c2455f3..c9eee2f 100644 --- a/toc.json +++ b/toc.json @@ -159,6 +159,11 @@ "type": "item", "title": "JWT Token", "uri": "docs/Backend_tutorials/features/jwt_token.md" + }, + { + "type": "item", + "title": "Easy Form", + "uri": "docs/Backend_tutorials/features/easy_form.md" } ] }, From d50be013ea430b2114a9a825a7de6f0070c3e8ee Mon Sep 17 00:00:00 2001 From: martin Date: Fri, 6 Jun 2025 14:29:33 +0200 Subject: [PATCH 2/4] refactor version warning --- docs/Backend_tutorials/features/easy_form.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Backend_tutorials/features/easy_form.md b/docs/Backend_tutorials/features/easy_form.md index 6e15275..0245d80 100644 --- a/docs/Backend_tutorials/features/easy_form.md +++ b/docs/Backend_tutorials/features/easy_form.md @@ -1,6 +1,6 @@ # Easy Form -Warning: V15 required! +⚠️ **Warning:** Easy Form components require application code on version **v15 or higher**. Easy Form is a new approach for building forms in ERB templates for application version V15 and higher. It aims to simplify form construction, reduce repetitive code, reduce level of customization From 3eb1d2e53b0ef42655bcde59f9b54bef0ecac668 Mon Sep 17 00:00:00 2001 From: martin Date: Tue, 17 Jun 2025 14:20:25 +0200 Subject: [PATCH 3/4] refactor components documentation by refactored code. --- docs/Backend_tutorials/features/easy_form.md | 67 ++++---------------- 1 file changed, 12 insertions(+), 55 deletions(-) diff --git a/docs/Backend_tutorials/features/easy_form.md b/docs/Backend_tutorials/features/easy_form.md index 0245d80..4d8036c 100644 --- a/docs/Backend_tutorials/features/easy_form.md +++ b/docs/Backend_tutorials/features/easy_form.md @@ -49,66 +49,23 @@ Optional arguments are: ## EasyFormBuilder `EasyFormBuilder` is a custom form builder that inherits from `ActionView::Helpers::FormBuilder` and provides interface for creating form fields with consistent styling and structure. -Source code is located in `app/utils/easy_extensions/easy_form_builder.rb`. +Source code is located in `app/east_design/easy_form_builder.rb`. -Builder methods either implements required html content or calls component to render it. +Builder includes concerns that represents components or inputs. Html structure, behaviour and usage of each method for individual form field/component are described in [Easy Storybook](https://es.easyproject.com/easy_storybook). ## Components -To make form construction more modular and expressive, Easy Form supports the use of form components. -A form component is a plain Ruby class responsible for rendering a specific part of a form — such as an input field, field_set, etc. -Each component follows consistent interface, making it easy to integrate and extend. - -Base interface provides class and instance method for rendering `render`. -Instance method is responsible for rendering component content and accepts block as optional argument. -Class method accepts any named arguments and block as well. Passes named arguments to instance constructor. -With initialized instance, it calls `render` with (optional) block. - -```ruby title="base component interface" lineNumbers -module EasyFormComponents - class Base - include ActionView::Helpers::TagHelper - include ActionView::Context - include Redmine::I18n - - def self.render(**, &) - new(**).render(&) - end - - def render(&_block) - raise NotImplementedError - end - - end -end -``` - -```Ruby title="example of component" lineNumbers -module EasyFormComponents - class TextField < Base - - # @param [EasyExtensions::EasyFormBuilder] builder - # @param [Symbol] field - # @param [Hash] options - def initialize(builder:, field:, options: {}) - @builder = builder - @field = field - @options = options - end - - def render - builder.text_field(field, options) - end - - private - - attr_reader :builder, :field, :options - end -end -``` - - +To make form construction more modular and expressive, Easy Form supports the use of form components. +A component is a plain Ruby module that encapsulates the rendering logic for a specific part of the form — such as an input field, fieldset, label, or hint. +These components are structured as modular concerns and included directly into the custom form builder class. +This allows components to define helper methods that extend the form builder’s public interface in a consistent and reusable way. +Each component defines one or more instance methods on the form builder (e.g., radio_button_fieldset, radio_button, etc.), +which can be used directly in erb templates. This methods may optionally support yielding a block for advanced behavior. +Each module may includes additional private methods exclusive for component logic. +Components are organized in `app/east_design/easy_form/` directory. +They are distributed into subdirectories by its nature, such as `inputs`, `components`. +Also there is module `EasyForm::BuilderUtils` designated for shared private method across multiple components. From 6dc49f80240a2c7c0ff9e3bd32e6cc50ff68d077 Mon Sep 17 00:00:00 2001 From: martin Date: Wed, 18 Jun 2025 15:26:06 +0200 Subject: [PATCH 4/4] correct name space --- docs/Backend_tutorials/features/easy_form.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Backend_tutorials/features/easy_form.md b/docs/Backend_tutorials/features/easy_form.md index 4d8036c..999d972 100644 --- a/docs/Backend_tutorials/features/easy_form.md +++ b/docs/Backend_tutorials/features/easy_form.md @@ -9,7 +9,7 @@ and encourage consistent structure and styling across views accordingly to desig Implementation is included as helper module `easy_form_helper.rb` within `EasyExtensions`. It contains two methods `easy_form_for` and `easy_form_tag`, which are used to create forms in views. -Both methods use `EasyExtensions::EasyFormBuilder` as a form builder to provide implementation of individual components. +Both methods use `EasyFormBuilder` as a form builder to provide implementation of individual components. ## easy_form_for `easy_form_for` is used to create forms for specific model. Mandatory argument for this method is `model` instance.