forest_admin_datasource_customizer 1.0.0.pre.beta.21 → 1.0.0.pre.beta.57

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.
Files changed (68) hide show
  1. checksums.yaml +4 -4
  2. data/forest_admin_datasource_customizer.gemspec +3 -2
  3. data/lib/forest_admin_datasource_customizer/collection_customizer.rb +292 -5
  4. data/lib/forest_admin_datasource_customizer/context/agent_customization_context.rb +18 -0
  5. data/lib/forest_admin_datasource_customizer/context/collection_customization_context.rb +15 -0
  6. data/lib/forest_admin_datasource_customizer/context/relaxed_wrappers/relaxed_collection.rb +50 -0
  7. data/lib/forest_admin_datasource_customizer/context/relaxed_wrappers/relaxed_data_source.rb +18 -0
  8. data/lib/forest_admin_datasource_customizer/datasource_customizer.rb +43 -13
  9. data/lib/forest_admin_datasource_customizer/decorators/action/action_collection_decorator.rb +137 -0
  10. data/lib/forest_admin_datasource_customizer/decorators/action/base_action.rb +67 -0
  11. data/lib/forest_admin_datasource_customizer/decorators/action/context/action_context.rb +56 -0
  12. data/lib/forest_admin_datasource_customizer/decorators/action/context/action_context_single.rb +26 -0
  13. data/lib/forest_admin_datasource_customizer/decorators/action/dynamic_field.rb +50 -0
  14. data/lib/forest_admin_datasource_customizer/decorators/action/result_builder.rb +68 -0
  15. data/lib/forest_admin_datasource_customizer/decorators/action/types/action_scope.rb +15 -0
  16. data/lib/forest_admin_datasource_customizer/decorators/action/types/field_type.rb +35 -0
  17. data/lib/forest_admin_datasource_customizer/decorators/action/widget_field.rb +357 -0
  18. data/lib/forest_admin_datasource_customizer/decorators/binary/binary_collection_decorator.rb +215 -0
  19. data/lib/forest_admin_datasource_customizer/decorators/binary/binary_helper.rb +17 -0
  20. data/lib/forest_admin_datasource_customizer/decorators/chart/chart_collection_decorator.rb +41 -0
  21. data/lib/forest_admin_datasource_customizer/decorators/chart/chart_context.rb +33 -0
  22. data/lib/forest_admin_datasource_customizer/decorators/chart/chart_datasource_decorator.rb +46 -0
  23. data/lib/forest_admin_datasource_customizer/decorators/chart/result_builder.rb +148 -0
  24. data/lib/forest_admin_datasource_customizer/decorators/computed/compute_collection_decorator.rb +115 -0
  25. data/lib/forest_admin_datasource_customizer/decorators/computed/computed_definition.rb +21 -0
  26. data/lib/forest_admin_datasource_customizer/decorators/computed/utils/computed_field.rb +74 -0
  27. data/lib/forest_admin_datasource_customizer/decorators/computed/utils/flattener.rb +49 -0
  28. data/lib/forest_admin_datasource_customizer/decorators/decorators_stack.rb +33 -4
  29. data/lib/forest_admin_datasource_customizer/decorators/hook/context/after/hook_after_aggregate_context.rb +18 -0
  30. data/lib/forest_admin_datasource_customizer/decorators/hook/context/after/hook_after_create_context.rb +18 -0
  31. data/lib/forest_admin_datasource_customizer/decorators/hook/context/after/hook_after_delete_context.rb +12 -0
  32. data/lib/forest_admin_datasource_customizer/decorators/hook/context/after/hook_after_list_context.rb +18 -0
  33. data/lib/forest_admin_datasource_customizer/decorators/hook/context/after/hook_after_update_context.rb +12 -0
  34. data/lib/forest_admin_datasource_customizer/decorators/hook/context/before/hook_before_aggregate_context.rb +20 -0
  35. data/lib/forest_admin_datasource_customizer/decorators/hook/context/before/hook_before_create_context.rb +18 -0
  36. data/lib/forest_admin_datasource_customizer/decorators/hook/context/before/hook_before_delete_context.rb +18 -0
  37. data/lib/forest_admin_datasource_customizer/decorators/hook/context/before/hook_before_list_context.rb +19 -0
  38. data/lib/forest_admin_datasource_customizer/decorators/hook/context/before/hook_before_update_context.rb +19 -0
  39. data/lib/forest_admin_datasource_customizer/decorators/hook/context/hook_context.rb +22 -0
  40. data/lib/forest_admin_datasource_customizer/decorators/hook/hook_collection_decorator.rb +95 -0
  41. data/lib/forest_admin_datasource_customizer/decorators/hook/hooks.rb +26 -0
  42. data/lib/forest_admin_datasource_customizer/decorators/operators_emulate/operators_emulate_collection_decorator.rb +118 -0
  43. data/lib/forest_admin_datasource_customizer/decorators/operators_equivalence/operators_equivalence_collection_decorator.rb +50 -0
  44. data/lib/forest_admin_datasource_customizer/decorators/override/context/create_override_customization_context.rb +16 -0
  45. data/lib/forest_admin_datasource_customizer/decorators/override/context/delete_override_customization_context.rb +16 -0
  46. data/lib/forest_admin_datasource_customizer/decorators/override/context/update_override_customization_context.rb +17 -0
  47. data/lib/forest_admin_datasource_customizer/decorators/override/override_collection_decorator.rb +49 -0
  48. data/lib/forest_admin_datasource_customizer/decorators/publication/publication_collection_decorator.rb +95 -0
  49. data/lib/forest_admin_datasource_customizer/decorators/publication/publication_datasource_decorator.rb +57 -0
  50. data/lib/forest_admin_datasource_customizer/decorators/relation/relation_collection_decorator.rb +268 -0
  51. data/lib/forest_admin_datasource_customizer/decorators/rename_collection/rename_collection_datasource_decorator.rb +70 -0
  52. data/lib/forest_admin_datasource_customizer/decorators/rename_collection/rename_collection_decorator.rb +37 -0
  53. data/lib/forest_admin_datasource_customizer/decorators/rename_field/rename_field_collection_decorator.rb +190 -0
  54. data/lib/forest_admin_datasource_customizer/decorators/schema/schema_collection_decorator.rb +21 -0
  55. data/lib/forest_admin_datasource_customizer/decorators/search/search_collection_decorator.rb +135 -0
  56. data/lib/forest_admin_datasource_customizer/decorators/segment/segment_collection_decorator.rb +60 -0
  57. data/lib/forest_admin_datasource_customizer/decorators/sort/sort_collection_decorator.rb +127 -0
  58. data/lib/forest_admin_datasource_customizer/decorators/validation/validation_collection_decorator.rb +82 -0
  59. data/lib/forest_admin_datasource_customizer/decorators/write/create_relations/create_relations_collection_decorator.rb +75 -0
  60. data/lib/forest_admin_datasource_customizer/decorators/write/update_relations/update_relations_collection_decorator.rb +96 -0
  61. data/lib/forest_admin_datasource_customizer/decorators/write/write_datasource_decorator.rb +14 -0
  62. data/lib/forest_admin_datasource_customizer/decorators/write/write_replace/write_customization_context.rb +18 -0
  63. data/lib/forest_admin_datasource_customizer/decorators/write/write_replace/write_replace_collection_decorator.rb +125 -0
  64. data/lib/forest_admin_datasource_customizer/plugins/add_external_relation.rb +27 -0
  65. data/lib/forest_admin_datasource_customizer/plugins/import_field.rb +74 -0
  66. data/lib/forest_admin_datasource_customizer/version.rb +1 -1
  67. metadata +84 -5
  68. data/README.md +0 -31
@@ -0,0 +1,67 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ class BaseAction
5
+ attr_reader :scope, :form, :is_generate_file, :execute
6
+
7
+ def initialize(scope:, form: nil, is_generate_file: false, &execute)
8
+ @scope = scope
9
+ @form = form
10
+ @is_generate_file = is_generate_file
11
+ @execute = execute
12
+ end
13
+
14
+ def build_fields
15
+ @form = @form&.map do |field|
16
+ case field[:widget]
17
+ when 'AddressAutocomplete'
18
+ WidgetField::AddressAutocompleteField.new(**field)
19
+ when 'Checkbox'
20
+ WidgetField::CheckboxField.new(**field)
21
+ when 'CheckboxGroup'
22
+ WidgetField::CheckboxGroupField.new(**field)
23
+ when 'ColorPicker'
24
+ WidgetField::ColorPickerField.new(**field)
25
+ when 'CurrencyInput'
26
+ WidgetField::CurrencyInputField.new(**field)
27
+ when 'DatePicker'
28
+ WidgetField::DatePickerField.new(**field)
29
+ when 'Dropdown'
30
+ WidgetField::DropdownField.new(**field)
31
+ when 'FilePicker'
32
+ WidgetField::FilePickerField.new(**field)
33
+ when 'JsonEditor'
34
+ WidgetField::JsonEditorField.new(**field)
35
+ when 'NumberInput'
36
+ WidgetField::NumberInputField.new(**field)
37
+ when 'NumberInputList'
38
+ WidgetField::NumberInputListField.new(**field)
39
+ when 'RadioGroup'
40
+ WidgetField::RadioGroupField.new(**field)
41
+ when 'RichText'
42
+ WidgetField::RichTextField.new(**field)
43
+ when 'TextArea'
44
+ WidgetField::TextAreaField.new(**field)
45
+ when 'TextInput'
46
+ WidgetField::TextInputField.new(**field)
47
+ when 'TextInputList'
48
+ WidgetField::TextInputListField.new(**field)
49
+ when 'TimePicker'
50
+ WidgetField::TimePickerField.new(**field)
51
+ when 'UserDropdown'
52
+ WidgetField::UserDropdownField.new(**field)
53
+ else
54
+ DynamicField.new(**field)
55
+ end
56
+ end
57
+ end
58
+
59
+ def static_form?
60
+ return form&.all?(&:static?) if form
61
+
62
+ true
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,56 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ module Context
5
+ class ActionContext < ForestAdminDatasourceCustomizer::Context::CollectionCustomizationContext
6
+ include ForestAdminDatasourceToolkit
7
+
8
+ attr_reader :filter, :used, :form_values
9
+
10
+ def initialize(collection, caller, form_values, filter, used = [], change_field = nil)
11
+ super(collection, caller)
12
+ @form_values = form_values
13
+ @filter = filter
14
+ @used = used
15
+ @change_field = change_field
16
+ end
17
+
18
+ def field_changed?(field_name)
19
+ @used << field_name
20
+
21
+ @change_field == field_name
22
+ end
23
+
24
+ def get_form_value(key)
25
+ @used << key
26
+
27
+ @form_values[key]
28
+ end
29
+
30
+ def get_records(fields = [])
31
+ Validations::ProjectionValidator.validate?(@real_collection, fields)
32
+
33
+ @real_collection.list(@caller, @filter, Components::Query::Projection.new)
34
+ end
35
+
36
+ def record_ids
37
+ composite_ids = composite_record_ids
38
+
39
+ composite_ids.map { |id| id[0] }
40
+ end
41
+
42
+ def composite_record_ids
43
+ projection = Components::Query::Projection.new.with_pks(@real_collection)
44
+ records = get_records(projection)
45
+
46
+ records.map { |record| Utils::Record.primary_keys(@real_collection, record) }
47
+ end
48
+
49
+ alias get_record_ids record_ids
50
+ alias get_composite_record_ids composite_record_ids
51
+ alias has_field_changed field_changed?
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,26 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ module Context
5
+ class ActionContextSingle < ActionContext
6
+ include ForestAdminDatasourceToolkit
7
+
8
+ def get_record(fields = [])
9
+ get_records(fields)[0]
10
+ end
11
+
12
+ def record_id
13
+ composite_record_id[0]
14
+ end
15
+
16
+ def composite_record_id
17
+ composite_record_ids[0]
18
+ end
19
+
20
+ alias get_record_id record_id
21
+ alias get_composite_record_id composite_record_id
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,50 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ class DynamicField
5
+ attr_accessor :type, :label, :description, :is_required, :is_read_only, :if_condition, :value, :default_value,
6
+ :collection_name, :enum_values, :placeholder
7
+
8
+ def initialize(
9
+ type:,
10
+ label:,
11
+ description: nil,
12
+ is_required: false,
13
+ is_read_only: false,
14
+ if_condition: nil,
15
+ value: nil,
16
+ default_value: nil,
17
+ collection_name: nil,
18
+ enum_values: nil,
19
+ placeholder: nil,
20
+ **_kwargs
21
+ )
22
+ @type = type
23
+ @label = label
24
+ @description = description
25
+ @is_required = is_required
26
+ @is_read_only = is_read_only
27
+ @if_condition = if_condition
28
+ @value = value
29
+ @default_value = default_value
30
+ @collection_name = collection_name
31
+ @enum_values = enum_values
32
+ @placeholder = placeholder
33
+ end
34
+
35
+ def static?
36
+ instance_variables.all? { |attribute| !instance_variable_get(attribute).respond_to?(:call) }
37
+ end
38
+
39
+ def to_h
40
+ result = {}
41
+ instance_variables.each do |attribute|
42
+ result[attribute.to_s.delete('@').to_sym] = instance_variable_get(attribute)
43
+ end
44
+
45
+ result
46
+ end
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,68 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ class ResultBuilder
5
+ def initialize
6
+ @headers = {}
7
+ end
8
+
9
+ def set_header(key, value)
10
+ @headers[key] = value
11
+
12
+ self
13
+ end
14
+
15
+ def success(message: 'Success', options: {})
16
+ {
17
+ headers: @headers,
18
+ type: 'Success',
19
+ message: message,
20
+ refresh: { relationships: options.key?(:invalidated) ? options[:invalidated] : [] },
21
+ html: options.key?(:html) ? options[:html] : nil
22
+ }
23
+ end
24
+
25
+ def error(message: 'Error', options: {})
26
+ {
27
+ headers: @headers,
28
+ type: 'Error',
29
+ status: 400,
30
+ message: message,
31
+ html: options.key?(:html) ? options[:html] : nil
32
+ }
33
+ end
34
+
35
+ def webhook(url:, method: 'POST', headers: {}, body: {})
36
+ {
37
+ headers: @headers,
38
+ type: 'Webhook',
39
+ webhook: {
40
+ body: body,
41
+ headers: headers,
42
+ method: method,
43
+ url: url
44
+ }
45
+ }
46
+ end
47
+
48
+ def file(content:, name: 'file', mime_type: 'application/octet-stream')
49
+ {
50
+ headers: @headers,
51
+ type: 'File',
52
+ name: name,
53
+ mime_type: mime_type,
54
+ stream: content
55
+ }
56
+ end
57
+
58
+ def redirect_to(path:)
59
+ {
60
+ headers: @headers,
61
+ type: 'Redirect',
62
+ redirect_to: path
63
+ }
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,15 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ module Types
5
+ module ActionScope
6
+ SINGLE = 'single'.freeze
7
+
8
+ BULK = 'bulk'.freeze
9
+
10
+ GLOBAL = 'global'.freeze
11
+ end
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,35 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ module Types
5
+ module FieldType
6
+ BOOLEAN = 'Boolean'.freeze
7
+
8
+ DATE = 'Date'.freeze
9
+
10
+ DATE_ONLY = 'Dateonly'.freeze
11
+
12
+ COLLECTION = 'Collection'.freeze
13
+
14
+ ENUM = 'Enum'.freeze
15
+
16
+ ENUM_LIST = 'EnumList'.freeze
17
+
18
+ FILE = 'File'.freeze
19
+
20
+ FILE_LIST = 'FileList'.freeze
21
+
22
+ JSON = 'Json'.freeze
23
+
24
+ NUMBER = 'Number'.freeze
25
+
26
+ NUMBER_LIST = 'NumberList'.freeze
27
+
28
+ STRING = 'String'.freeze
29
+
30
+ STRING_LIST = 'StringList'.freeze
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,357 @@
1
+ module ForestAdminDatasourceCustomizer
2
+ module Decorators
3
+ module Action
4
+ module WidgetField
5
+ include Types
6
+ def self.validate_arg(options, attribute, rule)
7
+ case rule[attribute]
8
+ when 'contains'
9
+ unless rule[:value].include? options[attribute]
10
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
11
+ "'#{attribute}' must have a value included in [#{rule[:value]}]"
12
+ end
13
+ when 'present'
14
+ unless options.key? attribute
15
+ raise ForestAdminDatasourceToolkit::Exceptions::ForestException,
16
+ "key '#{attribute}' must be defined"
17
+ end
18
+ end
19
+ end
20
+
21
+ class TimePickerField < DynamicField
22
+ attr_accessor :widget
23
+
24
+ def initialize(options)
25
+ super(**options)
26
+ WidgetField.validate_arg(options, :type, { type: 'contains', value: ['Time'] })
27
+ @widget = 'TimePicker'
28
+ end
29
+ end
30
+
31
+ class AddressAutocompleteField < DynamicField
32
+ attr_accessor :widget
33
+
34
+ def initialize(options)
35
+ super(**options)
36
+ WidgetField.validate_arg(options, :type, { type: 'contains', value: ['String'] })
37
+
38
+ @widget = 'AddressAutocomplete'
39
+ end
40
+ end
41
+
42
+ class CheckboxField < DynamicField
43
+ attr_accessor :widget
44
+
45
+ def initialize(options)
46
+ super(**options)
47
+ WidgetField.validate_arg(
48
+ options,
49
+ :type,
50
+ { type: 'contains', value: [Types::FieldType::BOOLEAN] }
51
+ )
52
+
53
+ @widget = 'Checkbox'
54
+ end
55
+ end
56
+
57
+ class CheckboxGroupField < DynamicField
58
+ attr_accessor :widget, :options
59
+
60
+ def initialize(options)
61
+ super(**options)
62
+
63
+ WidgetField.validate_arg(options, :options, { type: 'present' })
64
+ WidgetField.validate_arg(
65
+ options,
66
+ :type,
67
+ { type: 'contains', value: [Types::FieldType::STRING_LIST, Types::FieldType::NUMBER_LIST] }
68
+ )
69
+
70
+ @widget = 'CheckboxGroup'
71
+ @options = options[:options]
72
+ end
73
+ end
74
+
75
+ class ColorPickerField < DynamicField
76
+ attr_accessor :widget, :enable_opacity, :quick_palette
77
+
78
+ def initialize(options)
79
+ super(**options)
80
+
81
+ WidgetField.validate_arg(options, :enable_opacity, { type: 'contains', value: [Types::FieldType::STRING] })
82
+
83
+ @widget = 'ColorPicker'
84
+ @enable_opacity = options[:enable_opacity] || nil
85
+ @quick_palette = options[:quick_palette] || nil
86
+ end
87
+ end
88
+
89
+ class CurrencyInputField < DynamicField
90
+ attr_accessor :widget, :currency, :base, :min, :max, :step
91
+
92
+ def initialize(options)
93
+ super(**options)
94
+
95
+ WidgetField.validate_arg(options, :type, { type: 'contains', value: [Types::FieldType::NUMBER] })
96
+ WidgetField.validate_arg(options, :currency, { type: 'present' })
97
+
98
+ @widget = 'CurrencyInput'
99
+ @currency = options[:currency]
100
+ @base = options[:base] || 'Unit'
101
+ @min = options[:min] || nil
102
+ @max = options[:max] || nil
103
+ @step = options[:step] || nil
104
+ end
105
+ end
106
+
107
+ class DatePickerField < DynamicField
108
+ attr_accessor :widget, :min, :max, :format, :step
109
+
110
+ def initialize(options)
111
+ super(**options)
112
+
113
+ WidgetField.validate_arg(
114
+ options,
115
+ 'type',
116
+ { type: 'contains',
117
+ value: [Types::FieldType::DATE, Types::FieldType::DATE_ONLY, Types::FieldType::STRING] }
118
+ )
119
+
120
+ @widget = 'DatePicker'
121
+ @format = options[:format] || nil
122
+ @min = options[:min] || nil
123
+ @max = options[:max] || nil
124
+ @step = options[:step] || nil
125
+ end
126
+ end
127
+
128
+ class DropdownField < DynamicField
129
+ attr_accessor :widget, :options, :search
130
+
131
+ def initialize(options)
132
+ super(**options)
133
+ WidgetField.validate_arg(options, :options, { type: 'present' })
134
+ WidgetField.validate_arg(
135
+ options,
136
+ 'type',
137
+ {
138
+ type: 'contains',
139
+ value: [Types::FieldType::DATE, Types::FieldType::DATE_ONLY, Types::FieldType::STRING,
140
+ Types::FieldType::STRING_LIST]
141
+ }
142
+ )
143
+
144
+ @widget = 'Dropdown'
145
+ @options = options[:options]
146
+ @search = options[:search] || nil
147
+ end
148
+ end
149
+
150
+ class FilePickerField < DynamicField
151
+ attr_accessor :widget, :extensions, :max_count, :max_size_mb
152
+
153
+ def initialize(options)
154
+ super(**options)
155
+ WidgetField.validate_arg(options, :options, { type: 'present' })
156
+ WidgetField.validate_arg(
157
+ options,
158
+ 'type',
159
+ {
160
+ type: 'contains',
161
+ value: [Types::FieldType::FILE, Types::FieldType::FILE_LIST]
162
+ }
163
+ )
164
+
165
+ @widget = 'FilePicker'
166
+ @extensions = options[:extensions] || nil
167
+ @max_size_mb = options[:max_size_mb] || nil
168
+ @max_count = options[:max_count] || nil
169
+ end
170
+ end
171
+
172
+ class NumberInputField < DynamicField
173
+ attr_accessor :widget, :step, :min, :max
174
+
175
+ def initialize(options)
176
+ super(**options)
177
+ WidgetField.validate_arg(options, :options, { type: 'present' })
178
+ WidgetField.validate_arg(
179
+ options,
180
+ 'type',
181
+ {
182
+ type: 'contains',
183
+ value: [Types::FieldType::NUMBER]
184
+ }
185
+ )
186
+
187
+ @widget = 'NumberInput'
188
+ @step = options[:step] || nil
189
+ @min = options[:min] || nil
190
+ @max = options[:max] || nil
191
+ end
192
+ end
193
+
194
+ class JsonEditorField < DynamicField
195
+ attr_accessor :widget
196
+
197
+ def initialize(options)
198
+ super(**options)
199
+ WidgetField.validate_arg(
200
+ options,
201
+ 'type',
202
+ {
203
+ type: 'contains',
204
+ value: [Types::FieldType::DATE, Types::FieldType::DATE_ONLY, Types::FieldType::STRING,
205
+ Types::FieldType::STRING_LIST]
206
+ }
207
+ )
208
+
209
+ @widget = 'JsonEditor'
210
+ end
211
+ end
212
+
213
+ class NumberInputListField < DynamicField
214
+ attr_accessor :widget, :allow_duplicates, :allow_empty_values, :enable_reorder, :min, :max, :step
215
+
216
+ def initialize(options)
217
+ super(**options)
218
+ WidgetField.validate_arg(options, :options, { type: 'present' })
219
+ WidgetField.validate_arg(
220
+ options,
221
+ 'type',
222
+ {
223
+ type: 'contains',
224
+ value: [Types::FieldType::NUMBER_LIST]
225
+ }
226
+ )
227
+
228
+ @widget = 'NumberInputList'
229
+ @allow_duplicates = options[:allow_duplicates] || nil
230
+ @allow_empty_values = options[:allow_empty_values] || nil
231
+ @enable_reorder = options[:enable_reorder] || nil
232
+ @min = options[:min] || nil
233
+ @max = options[:max] || nil
234
+ @step = options[:step] || nil
235
+ end
236
+ end
237
+
238
+ class RadioGroupField < DynamicField
239
+ attr_accessor :widget, :options
240
+
241
+ def initialize(options)
242
+ super(**options)
243
+ WidgetField.validate_arg(options, :options, { type: 'present' })
244
+ WidgetField.validate_arg(
245
+ options,
246
+ 'type',
247
+ {
248
+ type: 'contains',
249
+ value: [Types::FieldType::DATE, Types::FieldType::DATEONLY, Types::FieldType::NUMBER,
250
+ Types::FieldType::STRING]
251
+ }
252
+ )
253
+
254
+ @widget = 'RadioGroup'
255
+ @options = options[:options]
256
+ end
257
+ end
258
+
259
+ class RichTextField < DynamicField
260
+ attr_accessor :widget
261
+
262
+ def initialize(options)
263
+ super(**options)
264
+ WidgetField.validate_arg(options, :options, { type: 'present' })
265
+ WidgetField.validate_arg(
266
+ options,
267
+ 'type',
268
+ {
269
+ type: 'contains',
270
+ value: [Types::FieldType::STRING]
271
+ }
272
+ )
273
+
274
+ @widget = 'RichText'
275
+ end
276
+ end
277
+
278
+ class TextAreaField < DynamicField
279
+ attr_accessor :widget, :rows
280
+
281
+ def initialize(options)
282
+ super(**options)
283
+ WidgetField.validate_arg(
284
+ options,
285
+ 'type',
286
+ {
287
+ type: 'contains',
288
+ value: [Types::FieldType::STRING]
289
+ }
290
+ )
291
+
292
+ @widget = 'TextArea'
293
+ @rows = options[:rows] || nil
294
+ end
295
+ end
296
+
297
+ class TextInputField < DynamicField
298
+ attr_accessor :widget
299
+
300
+ def initialize(options)
301
+ super(**options)
302
+ WidgetField.validate_arg(
303
+ options,
304
+ 'type',
305
+ {
306
+ type: 'contains',
307
+ value: [Types::FieldType::STRING]
308
+ }
309
+ )
310
+
311
+ @widget = 'TextInput'
312
+ end
313
+ end
314
+
315
+ class TextInputListField < DynamicField
316
+ attr_accessor :widget, :allow_duplicates, :allow_empty_values, :enable_reorder
317
+
318
+ def initialize(options)
319
+ super(**options)
320
+ WidgetField.validate_arg(
321
+ options,
322
+ 'type',
323
+ {
324
+ type: 'contains',
325
+ value: [Types::FieldType::STRING_LIST]
326
+ }
327
+ )
328
+
329
+ @widget = 'TextInput'
330
+ @allow_duplicates = options[:allow_duplicates] || nil
331
+ @allow_empty_values = options[:allow_empty_values] || nil
332
+ @enable_reorder = options[:enable_reorder] || nil
333
+ end
334
+ end
335
+
336
+ class UserDropdownField < DynamicField
337
+ attr_accessor :widget
338
+
339
+ def initialize(options)
340
+ super(**options)
341
+ WidgetField.validate_arg(options, :options, { type: 'present' })
342
+ WidgetField.validate_arg(
343
+ options,
344
+ 'type',
345
+ {
346
+ type: 'contains',
347
+ value: [Types::FieldType::STRING, Types::FieldType::STRING_LIST]
348
+ }
349
+ )
350
+
351
+ @widget = 'UserDropdown'
352
+ end
353
+ end
354
+ end
355
+ end
356
+ end
357
+ end