forest_admin_datasource_customizer 1.0.0.pre.beta.69 → 1.0.0.pre.beta.70

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: e1c8a06acb9a7a54a9b3307d8ced770afb79f524830002e3df64a0c4d2942663
4
- data.tar.gz: 42839a7a96efa461771180ccfc4c7eeba8c111d35fef2c9677f09a9e264b2dad
3
+ metadata.gz: f034b46ebd5986948532a00416d5035ef436870de4e924f75fe88ff91041faaa
4
+ data.tar.gz: 22158ab749cfccd936e41bec2f5c6e3277204e75c76ea797b5ec53c72a07f046
5
5
  SHA512:
6
- metadata.gz: 4d0c9a2a6baa9054af52915b4987b570acc90376dc2f66ecaaae3749c1b59752968e6e4f85c8f91f2f7a1910312b9f9ebd51e1225a2c5dbfafd43bfc360a6a70
7
- data.tar.gz: e184b1912374f9f8aca77f44a97b1d4b3d0e09d87eccaab1a9332d1e3039e040ff9a201cafefb3641f27e0fe90b11d4424aded5b503a43e42f67dd56162b052c
6
+ metadata.gz: 147f550e178d540665fe1762dbd47f2ff0c9618f81d9d0d50ef4072e126f0ae42eafe8ed3774e1a85035fd1c653e7742d656a435c2887af7cc3c3e42d9e1959f
7
+ data.tar.gz: 84e3b3a9920fef9e7b8aa77806d454ee6d9df0215c4ef2fe539509482555ae53c87969aaa979f113ca9ac39177c3c2aeb4472ddd004fe414cca6d29637315d1e
@@ -11,6 +11,7 @@ module ForestAdminDatasourceCustomizer
11
11
 
12
12
  def add_action(name, action)
13
13
  action.build_elements
14
+ action.validate_fields_ids
14
15
  @actions[name] = action
15
16
 
16
17
  mark_schema_as_dirty
@@ -43,24 +44,14 @@ module ForestAdminDatasourceCustomizer
43
44
  if metas[:search_field]
44
45
  # in the case of a search hook,
45
46
  # we don't want to rebuild all the fields. only the one searched
46
- dynamic_fields = dynamic_fields.select { |field| field.label == metas[:search_field] }
47
+ dynamic_fields = dynamic_fields.select { |field| field.id == metas[:search_field] }
47
48
  end
48
49
  dynamic_fields = drop_defaults(context, dynamic_fields, form_values)
49
50
  dynamic_fields = drop_ifs(context, dynamic_fields) unless metas[:include_hidden_fields]
50
51
 
51
52
  fields = drop_deferred(context, metas[:search_values], dynamic_fields).compact
52
53
 
53
- fields.each do |field|
54
- next if field.type == 'Layout'
55
-
56
- if field.value.nil?
57
- # customer did not define a handler to rewrite the previous value => reuse current one.
58
- field.value = form_values[field.label]
59
- end
60
-
61
- # fields that were accessed through the context.get_form_value(x) getter should be watched.
62
- field.watch_changes = used.include?(field.label)
63
- end
54
+ set_watch_changes_on_fields(form_values, used, fields)
64
55
 
65
56
  fields
66
57
  end
@@ -73,9 +64,34 @@ module ForestAdminDatasourceCustomizer
73
64
 
74
65
  private
75
66
 
67
+ def set_watch_changes_on_fields(form_values, used, fields)
68
+ fields.each do |field|
69
+ if field.type != 'Layout'
70
+
71
+ if field.value.nil?
72
+ # customer did not define a handler to rewrite the previous value => reuse current one.
73
+ field.value = form_values[field.id]
74
+ end
75
+
76
+ # fields that were accessed through the context.get_form_value(x) getter should be watched.
77
+ field.watch_changes = used.include?(field.id)
78
+ elsif field.component == 'Row'
79
+ set_watch_changes_on_fields(form_values, used, field.fields)
80
+ end
81
+ end
82
+ end
83
+
84
+ def execute_on_sub_fields(field)
85
+ return unless field.type == 'Layout' && field.component == 'Row'
86
+
87
+ field.fields = yield(field.fields)
88
+ end
89
+
76
90
  def drop_defaults(context, fields, data)
77
91
  fields.map do |field|
78
92
  if field.type == 'Layout'
93
+ execute_on_sub_fields(field) { |sub_fields| drop_defaults(context, sub_fields, data) }
94
+
79
95
  field
80
96
  else
81
97
  drop_default(context, field, data)
@@ -84,14 +100,25 @@ module ForestAdminDatasourceCustomizer
84
100
  end
85
101
 
86
102
  def drop_default(context, field, data)
87
- data[field.label] = evaluate(context, field.default_value) unless data.key?(field.label)
103
+ data[field.id] = evaluate(context, field.default_value) unless data.key?(field.id)
88
104
  field.default_value = nil
89
105
 
90
106
  field
91
107
  end
92
108
 
93
109
  def drop_ifs(context, fields)
94
- if_values = fields.map { |field| !field.if_condition || evaluate(context, field.if_condition) }
110
+ if_values = fields.map do |field|
111
+ if evaluate(context, field.if_condition) == false
112
+ false
113
+ elsif field.type == 'Layout' && field.component == 'Row'
114
+ field.fields = drop_ifs(context, field.fields || [])
115
+
116
+ true unless field.fields.empty?
117
+ else
118
+ true
119
+ end
120
+ end
121
+
95
122
  new_fields = fields.select.with_index { |_field, index| if_values[index] }
96
123
  new_fields.each do |field|
97
124
  field = field.dup
@@ -105,6 +132,8 @@ module ForestAdminDatasourceCustomizer
105
132
  new_fields = []
106
133
  fields.each do |field|
107
134
  field = field.dup
135
+ execute_on_sub_fields(field) { |sub_fields| drop_deferred(context, search_values, sub_fields) }
136
+
108
137
  field.instance_variables.each do |key|
109
138
  key = key.to_s.delete('@').to_sym
110
139
 
@@ -114,7 +143,7 @@ module ForestAdminDatasourceCustomizer
114
143
  value = field.send(key)
115
144
  key = key.to_s.concat('=').to_sym
116
145
 
117
- search_value = field.type == 'Layout' ? nil : search_values&.dig(field.label)
146
+ search_value = field.type == 'Layout' ? nil : search_values&.dig(field.id)
118
147
  field.send(key, evaluate(context, value, search_value))
119
148
  end
120
149
 
@@ -23,6 +23,20 @@ module ForestAdminDatasourceCustomizer
23
23
  end
24
24
  end
25
25
 
26
+ def validate_fields_ids(form = @form, used = [])
27
+ form&.each do |element|
28
+ if element.type == 'Layout' && element.component == 'Row'
29
+ validate_fields_ids(element.fields, used)
30
+ else
31
+ if used.include?(element.id)
32
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
33
+ "All field must have different 'id'. Conflict come from field '#{element.id}'"
34
+ end
35
+ used << element.id
36
+ end
37
+ end
38
+ end
39
+
26
40
  def build_widget(field)
27
41
  case field[:widget]
28
42
  when 'AddressAutocomplete'
@@ -3,11 +3,12 @@ module ForestAdminDatasourceCustomizer
3
3
  module Action
4
4
  class DynamicField < BaseFormElement
5
5
  attr_accessor :type, :label, :description, :is_required, :is_read_only, :if_condition, :value, :default_value,
6
- :collection_name, :enum_values, :placeholder
6
+ :collection_name, :enum_values, :placeholder, :id
7
7
 
8
8
  def initialize(
9
9
  type:,
10
- label:,
10
+ label: nil,
11
+ id: nil,
11
12
  description: nil,
12
13
  is_required: false,
13
14
  is_read_only: false,
@@ -21,7 +22,13 @@ module ForestAdminDatasourceCustomizer
21
22
  )
22
23
  super(type: type)
23
24
 
24
- @label = label
25
+ if id.nil? && label.nil?
26
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
27
+ "A field must have an 'id' or a 'label' defined."
28
+ end
29
+
30
+ @label = label.nil? ? id : label
31
+ @id = id.nil? ? label : id
25
32
  @description = description
26
33
  @is_required = is_required
27
34
  @is_read_only = is_read_only
@@ -32,6 +32,7 @@ module ForestAdminDatasourceCustomizer
32
32
 
33
33
  class RowElement < LayoutElement
34
34
  include ForestAdminDatasourceToolkit::Exceptions
35
+
35
36
  attr_accessor :fields
36
37
 
37
38
  def initialize(options)
@@ -58,7 +59,7 @@ module ForestAdminDatasourceCustomizer
58
59
 
59
60
  def instantiate_subfields(fields)
60
61
  fields.map do |field|
61
- ForestAdminDatasourceToolkit::Components::Actions::ActionFieldFactory.build(field.to_h)
62
+ DynamicField.new(**field.to_h)
62
63
  end
63
64
  end
64
65
  end
@@ -1,3 +1,3 @@
1
1
  module ForestAdminDatasourceCustomizer
2
- VERSION = "1.0.0-beta.69"
2
+ VERSION = "1.0.0-beta.70"
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.69
4
+ version: 1.0.0.pre.beta.70
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-09-25 00:00:00.000000000 Z
12
+ date: 2024-09-27 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activesupport
@@ -86,7 +86,6 @@ files:
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
88
  - lib/forest_admin_datasource_customizer/decorators/action/form_layout_element.rb
89
- - lib/forest_admin_datasource_customizer/decorators/action/layout_element.rb
90
89
  - lib/forest_admin_datasource_customizer/decorators/action/result_builder.rb
91
90
  - lib/forest_admin_datasource_customizer/decorators/action/types/action_scope.rb
92
91
  - lib/forest_admin_datasource_customizer/decorators/action/types/field_type.rb
@@ -1,343 +0,0 @@
1
- module ForestAdminDatasourceCustomizer
2
- module Decorators
3
- module Action
4
- module LayoutElement
5
- include Types
6
-
7
- class TimePickerField < DynamicField
8
- attr_accessor :widget
9
-
10
- def initialize(options)
11
- super(**options)
12
- WidgetField.validate_arg(options, :type, { type: 'contains', value: ['Time'] })
13
- @widget = 'TimePicker'
14
- end
15
- end
16
-
17
- class AddressAutocompleteField < DynamicField
18
- attr_accessor :widget
19
-
20
- def initialize(options)
21
- super(**options)
22
- WidgetField.validate_arg(options, :type, { type: 'contains', value: ['String'] })
23
-
24
- @widget = 'AddressAutocomplete'
25
- end
26
- end
27
-
28
- class CheckboxField < DynamicField
29
- attr_accessor :widget
30
-
31
- def initialize(options)
32
- super(**options)
33
- WidgetField.validate_arg(
34
- options,
35
- :type,
36
- { type: 'contains', value: [Types::FieldType::BOOLEAN] }
37
- )
38
-
39
- @widget = 'Checkbox'
40
- end
41
- end
42
-
43
- class CheckboxGroupField < DynamicField
44
- attr_accessor :widget, :options
45
-
46
- def initialize(options)
47
- super(**options)
48
-
49
- WidgetField.validate_arg(options, :options, { type: 'present' })
50
- WidgetField.validate_arg(
51
- options,
52
- :type,
53
- { type: 'contains', value: [Types::FieldType::STRING_LIST, Types::FieldType::NUMBER_LIST] }
54
- )
55
-
56
- @widget = 'CheckboxGroup'
57
- @options = options[:options]
58
- end
59
- end
60
-
61
- class ColorPickerField < DynamicField
62
- attr_accessor :widget, :enable_opacity, :quick_palette
63
-
64
- def initialize(options)
65
- super(**options)
66
-
67
- WidgetField.validate_arg(options, :enable_opacity, { type: 'contains', value: [Types::FieldType::STRING] })
68
-
69
- @widget = 'ColorPicker'
70
- @enable_opacity = options[:enable_opacity] || nil
71
- @quick_palette = options[:quick_palette] || nil
72
- end
73
- end
74
-
75
- class CurrencyInputField < DynamicField
76
- attr_accessor :widget, :currency, :base, :min, :max, :step
77
-
78
- def initialize(options)
79
- super(**options)
80
-
81
- WidgetField.validate_arg(options, :type, { type: 'contains', value: [Types::FieldType::NUMBER] })
82
- WidgetField.validate_arg(options, :currency, { type: 'present' })
83
-
84
- @widget = 'CurrencyInput'
85
- @currency = options[:currency]
86
- @base = options[:base] || 'Unit'
87
- @min = options[:min] || nil
88
- @max = options[:max] || nil
89
- @step = options[:step] || nil
90
- end
91
- end
92
-
93
- class DatePickerField < DynamicField
94
- attr_accessor :widget, :min, :max, :format, :step
95
-
96
- def initialize(options)
97
- super(**options)
98
-
99
- WidgetField.validate_arg(
100
- options,
101
- 'type',
102
- { type: 'contains',
103
- value: [Types::FieldType::DATE, Types::FieldType::DATE_ONLY, Types::FieldType::STRING] }
104
- )
105
-
106
- @widget = 'DatePicker'
107
- @format = options[:format] || nil
108
- @min = options[:min] || nil
109
- @max = options[:max] || nil
110
- @step = options[:step] || nil
111
- end
112
- end
113
-
114
- class DropdownField < DynamicField
115
- attr_accessor :widget, :options, :search
116
-
117
- def initialize(options)
118
- super(**options)
119
- WidgetField.validate_arg(options, :options, { type: 'present' })
120
- WidgetField.validate_arg(
121
- options,
122
- 'type',
123
- {
124
- type: 'contains',
125
- value: [Types::FieldType::DATE, Types::FieldType::DATE_ONLY, Types::FieldType::STRING,
126
- Types::FieldType::STRING_LIST]
127
- }
128
- )
129
-
130
- @widget = 'Dropdown'
131
- @options = options[:options]
132
- @search = options[:search] || nil
133
- end
134
- end
135
-
136
- class FilePickerField < DynamicField
137
- attr_accessor :widget, :extensions, :max_count, :max_size_mb
138
-
139
- def initialize(options)
140
- super(**options)
141
- WidgetField.validate_arg(options, :options, { type: 'present' })
142
- WidgetField.validate_arg(
143
- options,
144
- 'type',
145
- {
146
- type: 'contains',
147
- value: [Types::FieldType::FILE, Types::FieldType::FILE_LIST]
148
- }
149
- )
150
-
151
- @widget = 'FilePicker'
152
- @extensions = options[:extensions] || nil
153
- @max_size_mb = options[:max_size_mb] || nil
154
- @max_count = options[:max_count] || nil
155
- end
156
- end
157
-
158
- class NumberInputField < DynamicField
159
- attr_accessor :widget, :step, :min, :max
160
-
161
- def initialize(options)
162
- super(**options)
163
- WidgetField.validate_arg(options, :options, { type: 'present' })
164
- WidgetField.validate_arg(
165
- options,
166
- 'type',
167
- {
168
- type: 'contains',
169
- value: [Types::FieldType::NUMBER]
170
- }
171
- )
172
-
173
- @widget = 'NumberInput'
174
- @step = options[:step] || nil
175
- @min = options[:min] || nil
176
- @max = options[:max] || nil
177
- end
178
- end
179
-
180
- class JsonEditorField < DynamicField
181
- attr_accessor :widget
182
-
183
- def initialize(options)
184
- super(**options)
185
- WidgetField.validate_arg(
186
- options,
187
- 'type',
188
- {
189
- type: 'contains',
190
- value: [Types::FieldType::DATE, Types::FieldType::DATE_ONLY, Types::FieldType::STRING,
191
- Types::FieldType::STRING_LIST]
192
- }
193
- )
194
-
195
- @widget = 'JsonEditor'
196
- end
197
- end
198
-
199
- class NumberInputListField < DynamicField
200
- attr_accessor :widget, :allow_duplicates, :allow_empty_values, :enable_reorder, :min, :max, :step
201
-
202
- def initialize(options)
203
- super(**options)
204
- WidgetField.validate_arg(options, :options, { type: 'present' })
205
- WidgetField.validate_arg(
206
- options,
207
- 'type',
208
- {
209
- type: 'contains',
210
- value: [Types::FieldType::NUMBER_LIST]
211
- }
212
- )
213
-
214
- @widget = 'NumberInputList'
215
- @allow_duplicates = options[:allow_duplicates] || nil
216
- @allow_empty_values = options[:allow_empty_values] || nil
217
- @enable_reorder = options[:enable_reorder] || nil
218
- @min = options[:min] || nil
219
- @max = options[:max] || nil
220
- @step = options[:step] || nil
221
- end
222
- end
223
-
224
- class RadioGroupField < DynamicField
225
- attr_accessor :widget, :options
226
-
227
- def initialize(options)
228
- super(**options)
229
- WidgetField.validate_arg(options, :options, { type: 'present' })
230
- WidgetField.validate_arg(
231
- options,
232
- 'type',
233
- {
234
- type: 'contains',
235
- value: [Types::FieldType::DATE, Types::FieldType::DATEONLY, Types::FieldType::NUMBER,
236
- Types::FieldType::STRING]
237
- }
238
- )
239
-
240
- @widget = 'RadioGroup'
241
- @options = options[:options]
242
- end
243
- end
244
-
245
- class RichTextField < DynamicField
246
- attr_accessor :widget
247
-
248
- def initialize(options)
249
- super(**options)
250
- WidgetField.validate_arg(options, :options, { type: 'present' })
251
- WidgetField.validate_arg(
252
- options,
253
- 'type',
254
- {
255
- type: 'contains',
256
- value: [Types::FieldType::STRING]
257
- }
258
- )
259
-
260
- @widget = 'RichText'
261
- end
262
- end
263
-
264
- class TextAreaField < DynamicField
265
- attr_accessor :widget, :rows
266
-
267
- def initialize(options)
268
- super(**options)
269
- WidgetField.validate_arg(
270
- options,
271
- 'type',
272
- {
273
- type: 'contains',
274
- value: [Types::FieldType::STRING]
275
- }
276
- )
277
-
278
- @widget = 'TextArea'
279
- @rows = options[:rows] || nil
280
- end
281
- end
282
-
283
- class TextInputField < DynamicField
284
- attr_accessor :widget
285
-
286
- def initialize(options)
287
- super(**options)
288
- WidgetField.validate_arg(
289
- options,
290
- 'type',
291
- {
292
- type: 'contains',
293
- value: [Types::FieldType::STRING]
294
- }
295
- )
296
-
297
- @widget = 'TextInput'
298
- end
299
- end
300
-
301
- class TextInputListField < DynamicField
302
- attr_accessor :widget, :allow_duplicates, :allow_empty_values, :enable_reorder
303
-
304
- def initialize(options)
305
- super(**options)
306
- WidgetField.validate_arg(
307
- options,
308
- 'type',
309
- {
310
- type: 'contains',
311
- value: [Types::FieldType::STRING_LIST]
312
- }
313
- )
314
-
315
- @widget = 'TextInput'
316
- @allow_duplicates = options[:allow_duplicates] || nil
317
- @allow_empty_values = options[:allow_empty_values] || nil
318
- @enable_reorder = options[:enable_reorder] || nil
319
- end
320
- end
321
-
322
- class UserDropdownField < DynamicField
323
- attr_accessor :widget
324
-
325
- def initialize(options)
326
- super(**options)
327
- WidgetField.validate_arg(options, :options, { type: 'present' })
328
- WidgetField.validate_arg(
329
- options,
330
- 'type',
331
- {
332
- type: 'contains',
333
- value: [Types::FieldType::STRING, Types::FieldType::STRING_LIST]
334
- }
335
- )
336
-
337
- @widget = 'UserDropdown'
338
- end
339
- end
340
- end
341
- end
342
- end
343
- end