forest_admin_datasource_customizer 1.0.0.pre.beta.71 → 1.0.0.pre.beta.73

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: acf9789efa0d33d4fb4c1c008172b3e7433610863e04bcadf82cd111cf44fb82
4
- data.tar.gz: af2d0729a383de6be9b6d5dd484d69e83e8ab55a7fa4830dc231855b2e967ec9
3
+ metadata.gz: d87a2beab2434ed7e6bbbea36b416894d9a8434f7b848b41d3bfafc252810d54
4
+ data.tar.gz: 5c6fd553fbe2f7605d6140545c9cfc4477e620c41a3ef80c132140249d60d318
5
5
  SHA512:
6
- metadata.gz: a8b0b580641d3fb79fedc6c1b1cb76b981dde4f6e8b4c060eec1f589b2a743374b3637ffee92dd296f2b46e64b92adef8acedae283387a2ccce6830fa900f10f
7
- data.tar.gz: fe6b6ca2d566333fc04e5a3d5135f68640f1cbe938de5d95ddcc21aefecdbfdd05357eb1b886177e24600de78a039079e72b055f90f071bdea44b083383af741
6
+ metadata.gz: f5b8b268a153d3c22325ed24153a13217813625a71598f626cb5a617a8d99238f240e90241aa0b3386bed471e706c51278a1809d83cbdd3e660c657c3500623b
7
+ data.tar.gz: 1473d96b63ea47d0ccebcea540e526339f8a201d12e6f6e5dbd636525e3ad0acbbedc51cdbb2b908b54f6cc525ca0c37fb378dc6e589199d9b8e732c46f494c4
@@ -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?) 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
@@ -42,6 +42,10 @@ module ForestAdminDatasourceCustomizer
42
42
  @fields = instantiate_subfields(options[:fields] || [])
43
43
  end
44
44
 
45
+ def static?
46
+ super && fields&.all?(&:static?)
47
+ end
48
+
45
49
  private
46
50
 
47
51
  def validate_fields_presence!(options)
@@ -58,10 +62,48 @@ module ForestAdminDatasourceCustomizer
58
62
  end
59
63
 
60
64
  def instantiate_subfields(fields)
61
- fields.map do |field|
62
- DynamicField.new(**field.to_h)
65
+ FormFactory.build_elements(fields)
66
+ end
67
+ end
68
+
69
+ class PageElement < LayoutElement
70
+ include ForestAdminDatasourceToolkit::Exceptions
71
+
72
+ attr_accessor :elements, :next_button_label, :previous_button_label
73
+
74
+ def initialize(options)
75
+ super(component: 'Page', **options)
76
+
77
+ validate_elements_presence!(options)
78
+ validate_no_page_elements!(options[:elements])
79
+ @next_button_label = options[:next_button_label]
80
+ @previous_button_label = options[:previous_button_label]
81
+ @elements = instantiate_elements(options[:elements] || [])
82
+ end
83
+
84
+ def static?
85
+ super && elements&.all?(&:static?)
86
+ end
87
+
88
+ private
89
+
90
+ def validate_elements_presence!(options)
91
+ return if options.key?(:elements)
92
+
93
+ raise ForestException, "Using 'elements' in a 'Page' configuration is mandatory"
94
+ end
95
+
96
+ def validate_no_page_elements!(elements)
97
+ elements&.each do |element|
98
+ if element[:component] == 'Page'
99
+ raise ForestException, "'Page' component cannot be used within 'elements'"
100
+ end
63
101
  end
64
102
  end
103
+
104
+ def instantiate_elements(elements)
105
+ FormFactory.build_elements(elements)
106
+ end
65
107
  end
66
108
  end
67
109
  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.73"
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.73
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-10 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