forest_admin_datasource_customizer 1.0.0.pre.beta.69 → 1.0.0.pre.beta.71

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: e1c8a06acb9a7a54a9b3307d8ced770afb79f524830002e3df64a0c4d2942663
4
- data.tar.gz: 42839a7a96efa461771180ccfc4c7eeba8c111d35fef2c9677f09a9e264b2dad
3
+ metadata.gz: acf9789efa0d33d4fb4c1c008172b3e7433610863e04bcadf82cd111cf44fb82
4
+ data.tar.gz: af2d0729a383de6be9b6d5dd484d69e83e8ab55a7fa4830dc231855b2e967ec9
5
5
  SHA512:
6
- metadata.gz: 4d0c9a2a6baa9054af52915b4987b570acc90376dc2f66ecaaae3749c1b59752968e6e4f85c8f91f2f7a1910312b9f9ebd51e1225a2c5dbfafd43bfc360a6a70
7
- data.tar.gz: e184b1912374f9f8aca77f44a97b1d4b3d0e09d87eccaab1a9332d1e3039e040ff9a201cafefb3641f27e0fe90b11d4424aded5b503a43e42f67dd56162b052c
6
+ metadata.gz: a8b0b580641d3fb79fedc6c1b1cb76b981dde4f6e8b4c060eec1f589b2a743374b3637ffee92dd296f2b46e64b92adef8acedae283387a2ccce6830fa900f10f
7
+ data.tar.gz: fe6b6ca2d566333fc04e5a3d5135f68640f1cbe938de5d95ddcc21aefecdbfdd05357eb1b886177e24600de78a039079e72b055f90f071bdea44b083383af741
@@ -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
 
@@ -2,12 +2,14 @@ module ForestAdminDatasourceCustomizer
2
2
  module Decorators
3
3
  module Action
4
4
  class BaseAction
5
- attr_reader :scope, :form, :is_generate_file, :execute
5
+ attr_reader :scope, :form, :is_generate_file, :description, :submit_button_label, :execute
6
6
 
7
- def initialize(scope:, form: nil, is_generate_file: false, &execute)
7
+ def initialize(scope:, form: nil, is_generate_file: false, description: nil, submit_button_label: nil, &execute)
8
8
  @scope = scope
9
9
  @form = form
10
10
  @is_generate_file = is_generate_file
11
+ @description = description
12
+ @submit_button_label = submit_button_label
11
13
  @execute = execute
12
14
  end
13
15
 
@@ -23,6 +25,20 @@ module ForestAdminDatasourceCustomizer
23
25
  end
24
26
  end
25
27
 
28
+ def validate_fields_ids(form = @form, used = [])
29
+ form&.each do |element|
30
+ if element.type == 'Layout' && element.component == 'Row'
31
+ validate_fields_ids(element.fields, used)
32
+ else
33
+ if used.include?(element.id)
34
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
35
+ "All field must have different 'id'. Conflict come from field '#{element.id}'"
36
+ end
37
+ used << element.id
38
+ end
39
+ end
40
+ end
41
+
26
42
  def build_widget(field)
27
43
  case field[:widget]
28
44
  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.71"
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.71
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-10-04 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