forest_admin_datasource_customizer 1.0.0.pre.beta.71 → 1.0.0.pre.beta.72

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acf9789efa0d33d4fb4c1c008172b3e7433610863e04bcadf82cd111cf44fb82
4
- data.tar.gz: af2d0729a383de6be9b6d5dd484d69e83e8ab55a7fa4830dc231855b2e967ec9
3
+ metadata.gz: 658c563d6a1a05ba3895d6ee03f130816566313ca15c3db156d729bac9c6f309
4
+ data.tar.gz: 67b1718e466dde2ec435a41d5a86f98d3265cd1ee0208336c7e5cc469875e1e1
5
5
  SHA512:
6
- metadata.gz: a8b0b580641d3fb79fedc6c1b1cb76b981dde4f6e8b4c060eec1f589b2a743374b3637ffee92dd296f2b46e64b92adef8acedae283387a2ccce6830fa900f10f
7
- data.tar.gz: fe6b6ca2d566333fc04e5a3d5135f68640f1cbe938de5d95ddcc21aefecdbfdd05357eb1b886177e24600de78a039079e72b055f90f071bdea44b083383af741
6
+ metadata.gz: 7198979d8381dd56cce59bbe447fb51a9132d4d635d6fa4673b5b6cbee55eab1e0d65ff0c249b2fa6f6706a2cb4e2079401f10c001352fe0f17735a36b6ce4ac
7
+ data.tar.gz: b9296fc4ed968c4d42c0b978e772807f758f0a81ec09a6662c5bb49dd97b2364b64a6ff5fd3265870e965779a0b08a32cacb4dd8f61c5876cd82890fd7aa2127
@@ -10,6 +10,7 @@ module ForestAdminDatasourceCustomizer
10
10
  end
11
11
 
12
12
  def add_action(name, action)
13
+ ensure_form_is_correct(action.form, name)
13
14
  action.build_elements
14
15
  action.validate_fields_ids
15
16
  @actions[name] = action
@@ -41,15 +42,13 @@ module ForestAdminDatasourceCustomizer
41
42
  context = get_context(caller, action, form_values, filter, used, metas[:change_field])
42
43
 
43
44
  dynamic_fields = action.form
44
- if metas[:search_field]
45
- # in the case of a search hook,
46
- # we don't want to rebuild all the fields. only the one searched
47
- dynamic_fields = dynamic_fields.select { |field| field.id == metas[:search_field] }
48
- end
45
+ dynamic_fields = select_in_form_fields(dynamic_fields, metas[:search_field]) if metas[:search_field]
49
46
  dynamic_fields = drop_defaults(context, dynamic_fields, form_values)
50
47
  dynamic_fields = drop_ifs(context, dynamic_fields) unless metas[:include_hidden_fields]
51
48
 
52
- fields = drop_deferred(context, metas[:search_values], dynamic_fields).compact
49
+ fields = drop_deferred(context, metas[:search_values], dynamic_fields)
50
+
51
+ fields.compact
53
52
 
54
53
  set_watch_changes_on_fields(form_values, used, fields)
55
54
 
@@ -64,6 +63,31 @@ module ForestAdminDatasourceCustomizer
64
63
 
65
64
  private
66
65
 
66
+ def ensure_form_is_correct(form, action_name)
67
+ return if form.nil? || form.empty?
68
+
69
+ is_page_component = ->(element) { element[:type] == 'Layout' && element[:component] == 'Page' }
70
+ pages = is_page_component.call(form.first)
71
+
72
+ form.each do |element|
73
+ if pages != is_page_component.call(element)
74
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
75
+ "You cannot mix pages and other form elements in smart action '#{action_name}' form"
76
+ end
77
+ end
78
+ end
79
+
80
+ def select_in_form_fields(fields, search_field)
81
+ fields.select do |field|
82
+ if nested_layout_element?(field)
83
+ key = field.component == 'Page' ? :elements : :fields
84
+ select_in_form_fields(field.public_send(:"#{key}"), search_field)
85
+ else
86
+ field.id == search_field
87
+ end
88
+ end
89
+ end
90
+
67
91
  def set_watch_changes_on_fields(form_values, used, fields)
68
92
  fields.each do |field|
69
93
  if field.type != 'Layout'
@@ -77,14 +101,20 @@ module ForestAdminDatasourceCustomizer
77
101
  field.watch_changes = used.include?(field.id)
78
102
  elsif field.component == 'Row'
79
103
  set_watch_changes_on_fields(form_values, used, field.fields)
104
+ elsif field.component == 'Page'
105
+ set_watch_changes_on_fields(form_values, used, field.elements)
80
106
  end
81
107
  end
82
108
  end
83
109
 
84
110
  def execute_on_sub_fields(field)
85
- return unless field.type == 'Layout' && field.component == 'Row'
111
+ return unless nested_layout_element?(field)
86
112
 
87
- field.fields = yield(field.fields)
113
+ if field.component == 'Page'
114
+ field.elements = yield(field.elements)
115
+ elsif field.component == 'Row'
116
+ field.fields = yield(field.fields)
117
+ end
88
118
  end
89
119
 
90
120
  def drop_defaults(context, fields, data)
@@ -110,10 +140,12 @@ module ForestAdminDatasourceCustomizer
110
140
  if_values = fields.map do |field|
111
141
  if evaluate(context, field.if_condition) == false
112
142
  false
113
- elsif field.type == 'Layout' && field.component == 'Row'
114
- field.fields = drop_ifs(context, field.fields || [])
143
+ elsif nested_layout_element?(field)
144
+ key = field.component == 'Page' ? :elements : :fields
145
+ field.public_send(:"#{key}=", drop_ifs(context, field.public_send(:"#{key}") || []))
146
+
147
+ true unless field.public_send(:"#{key}").empty?
115
148
 
116
- true unless field.fields.empty?
117
149
  else
118
150
  true
119
151
  end
@@ -170,6 +202,10 @@ module ForestAdminDatasourceCustomizer
170
202
 
171
203
  Context::ActionContext.new(self, caller, form_values, filter, used, change_field)
172
204
  end
205
+
206
+ def nested_layout_element?(field)
207
+ field.type == 'Layout' && %w[Page Row].include?(field.component)
208
+ end
173
209
  end
174
210
  end
175
211
  end
@@ -14,21 +14,22 @@ module ForestAdminDatasourceCustomizer
14
14
  end
15
15
 
16
16
  def build_elements
17
- @form = @form&.map do |field|
18
- if field.key? :widget
19
- build_widget(field)
20
- elsif field[:type] == 'Layout'
21
- build_layout_element(field)
22
- else
23
- DynamicField.new(**field)
24
- end
25
- end
17
+ @form = FormFactory.build_elements(form)
18
+ end
19
+
20
+ def static_form?
21
+ return form&.all?(&:static?) && form&.none? { |field| field.type == 'Layout' } if form
22
+
23
+ true
26
24
  end
27
25
 
28
26
  def validate_fields_ids(form = @form, used = [])
29
27
  form&.each do |element|
30
- if element.type == 'Layout' && element.component == 'Row'
31
- validate_fields_ids(element.fields, used)
28
+ if element.type == 'Layout'
29
+ if %w[Page Row].include?(element.component)
30
+ key = element.component == 'Page' ? :elements : :fields
31
+ validate_fields_ids(element.public_send(key), used)
32
+ end
32
33
  else
33
34
  if used.include?(element.id)
34
35
  raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
@@ -38,69 +39,6 @@ module ForestAdminDatasourceCustomizer
38
39
  end
39
40
  end
40
41
  end
41
-
42
- def build_widget(field)
43
- case field[:widget]
44
- when 'AddressAutocomplete'
45
- WidgetField::AddressAutocompleteField.new(**field)
46
- when 'Checkbox'
47
- WidgetField::CheckboxField.new(**field)
48
- when 'CheckboxGroup'
49
- WidgetField::CheckboxGroupField.new(**field)
50
- when 'ColorPicker'
51
- WidgetField::ColorPickerField.new(**field)
52
- when 'CurrencyInput'
53
- WidgetField::CurrencyInputField.new(**field)
54
- when 'DatePicker'
55
- WidgetField::DatePickerField.new(**field)
56
- when 'Dropdown'
57
- WidgetField::DropdownField.new(**field)
58
- when 'FilePicker'
59
- WidgetField::FilePickerField.new(**field)
60
- when 'JsonEditor'
61
- WidgetField::JsonEditorField.new(**field)
62
- when 'NumberInput'
63
- WidgetField::NumberInputField.new(**field)
64
- when 'NumberInputList'
65
- WidgetField::NumberInputListField.new(**field)
66
- when 'RadioGroup'
67
- WidgetField::RadioGroupField.new(**field)
68
- when 'RichText'
69
- WidgetField::RichTextField.new(**field)
70
- when 'TextArea'
71
- WidgetField::TextAreaField.new(**field)
72
- when 'TextInput'
73
- WidgetField::TextInputField.new(**field)
74
- when 'TextInputList'
75
- WidgetField::TextInputListField.new(**field)
76
- when 'TimePicker'
77
- WidgetField::TimePickerField.new(**field)
78
- when 'UserDropdown'
79
- WidgetField::UserDropdownField.new(**field)
80
- else
81
- raise ForestAdminDatasourceToolkit::Exceptions::ForestException, "Unknow widget type: #{field[:widget]}"
82
- end
83
- end
84
-
85
- def build_layout_element(field)
86
- case field[:component]
87
- when 'Separator'
88
- FormLayoutElement::SeparatorElement.new(**field)
89
- when 'HtmlBlock'
90
- FormLayoutElement::HtmlBlockElement.new(**field)
91
- when 'Row'
92
- FormLayoutElement::RowElement.new(**field)
93
- else
94
- raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
95
- "Unknow component type: #{field[:component]}"
96
- end
97
- end
98
-
99
- def static_form?
100
- return form&.all?(&:static?) && form&.none? { |field| field.type == 'Layout' } if form
101
-
102
- true
103
- end
104
42
  end
105
43
  end
106
44
  end
@@ -0,0 +1,87 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ class FormFactory
5
+ def self.build_elements(form)
6
+ form&.map do |field|
7
+ case field
8
+ when Hash
9
+ if field.key?(:widget)
10
+ build_widget(field)
11
+ elsif field[:type] == 'Layout'
12
+ build_layout_element(field)
13
+ else
14
+ DynamicField.new(**field)
15
+ end
16
+ when FormLayoutElement::RowElement
17
+ build_elements(field.fields)
18
+ when FormLayoutElement::PageElement
19
+ build_elements(field.elements)
20
+ else
21
+ field
22
+ end
23
+ end
24
+ end
25
+
26
+ def self.build_widget(field)
27
+ case field[:widget]
28
+ when 'AddressAutocomplete'
29
+ WidgetField::AddressAutocompleteField.new(**field)
30
+ when 'Checkbox'
31
+ WidgetField::CheckboxField.new(**field)
32
+ when 'CheckboxGroup'
33
+ WidgetField::CheckboxGroupField.new(**field)
34
+ when 'ColorPicker'
35
+ WidgetField::ColorPickerField.new(**field)
36
+ when 'CurrencyInput'
37
+ WidgetField::CurrencyInputField.new(**field)
38
+ when 'DatePicker'
39
+ WidgetField::DatePickerField.new(**field)
40
+ when 'Dropdown'
41
+ WidgetField::DropdownField.new(**field)
42
+ when 'FilePicker'
43
+ WidgetField::FilePickerField.new(**field)
44
+ when 'JsonEditor'
45
+ WidgetField::JsonEditorField.new(**field)
46
+ when 'NumberInput'
47
+ WidgetField::NumberInputField.new(**field)
48
+ when 'NumberInputList'
49
+ WidgetField::NumberInputListField.new(**field)
50
+ when 'RadioGroup'
51
+ WidgetField::RadioGroupField.new(**field)
52
+ when 'RichText'
53
+ WidgetField::RichTextField.new(**field)
54
+ when 'TextArea'
55
+ WidgetField::TextAreaField.new(**field)
56
+ when 'TextInput'
57
+ WidgetField::TextInputField.new(**field)
58
+ when 'TextInputList'
59
+ WidgetField::TextInputListField.new(**field)
60
+ when 'TimePicker'
61
+ WidgetField::TimePickerField.new(**field)
62
+ when 'UserDropdown'
63
+ WidgetField::UserDropdownField.new(**field)
64
+ else
65
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException, "Unknow widget type: #{field[:widget]}"
66
+ end
67
+ end
68
+
69
+ def self.build_layout_element(field)
70
+ case field[:component]
71
+ when 'Separator'
72
+ FormLayoutElement::SeparatorElement.new(**field)
73
+ when 'HtmlBlock'
74
+ FormLayoutElement::HtmlBlockElement.new(**field)
75
+ when 'Row'
76
+ FormLayoutElement::RowElement.new(**field)
77
+ when 'Page'
78
+ FormLayoutElement::PageElement.new(**field)
79
+ else
80
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
81
+ "Unknow component type: #{field[:component]}"
82
+ end
83
+ end
84
+ end
85
+ end
86
+ end
87
+ end
@@ -58,10 +58,44 @@ module ForestAdminDatasourceCustomizer
58
58
  end
59
59
 
60
60
  def instantiate_subfields(fields)
61
- fields.map do |field|
62
- DynamicField.new(**field.to_h)
61
+ FormFactory.build_elements(fields)
62
+ end
63
+ end
64
+
65
+ class PageElement < LayoutElement
66
+ include ForestAdminDatasourceToolkit::Exceptions
67
+
68
+ attr_accessor :elements, :next_button_label, :previous_button_label
69
+
70
+ def initialize(options)
71
+ super(component: 'Page', **options)
72
+
73
+ validate_elements_presence!(options)
74
+ validate_no_page_elements!(options[:elements])
75
+ @next_button_label = options[:next_button_label]
76
+ @previous_button_label = options[:previous_button_label]
77
+ @elements = instantiate_elements(options[:elements] || [])
78
+ end
79
+
80
+ private
81
+
82
+ def validate_elements_presence!(options)
83
+ return if options.key?(:elements)
84
+
85
+ raise ForestException, "Using 'elements' in a 'Page' configuration is mandatory"
86
+ end
87
+
88
+ def validate_no_page_elements!(elements)
89
+ elements&.each do |element|
90
+ if element[:component] == 'Page'
91
+ raise ForestException, "'Page' component cannot be used within 'elements'"
92
+ end
63
93
  end
64
94
  end
95
+
96
+ def instantiate_elements(elements)
97
+ FormFactory.build_elements(elements)
98
+ end
65
99
  end
66
100
  end
67
101
  end
@@ -21,6 +21,8 @@ module ForestAdminDatasourceCustomizer
21
21
 
22
22
  JSON = 'Json'.freeze
23
23
 
24
+ LAYOUT = 'Layout'.freeze
25
+
24
26
  NUMBER = 'Number'.freeze
25
27
 
26
28
  NUMBER_LIST = 'NumberList'.freeze
@@ -1,3 +1,3 @@
1
1
  module ForestAdminDatasourceCustomizer
2
- VERSION = "1.0.0-beta.71"
2
+ VERSION = "1.0.0-beta.72"
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: forest_admin_datasource_customizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.0.pre.beta.71
4
+ version: 1.0.0.pre.beta.72
5
5
  platform: ruby
6
6
  authors:
7
7
  - Matthieu
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: exe
11
11
  cert_chain: []
12
- date: 2024-10-04 00:00:00.000000000 Z
12
+ date: 2024-10-09 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -85,6 +85,7 @@ files:
85
85
  - lib/forest_admin_datasource_customizer/decorators/action/context/action_context.rb
86
86
  - lib/forest_admin_datasource_customizer/decorators/action/context/action_context_single.rb
87
87
  - lib/forest_admin_datasource_customizer/decorators/action/dynamic_field.rb
88
+ - lib/forest_admin_datasource_customizer/decorators/action/form_factory.rb
88
89
  - lib/forest_admin_datasource_customizer/decorators/action/form_layout_element.rb
89
90
  - lib/forest_admin_datasource_customizer/decorators/action/result_builder.rb
90
91
  - lib/forest_admin_datasource_customizer/decorators/action/types/action_scope.rb