forest_admin_agent 1.0.0.pre.beta.51 → 1.0.0.pre.beta.52
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 +4 -4
- data/lib/forest_admin_agent/routes/action/action.rb +10 -2
- data/lib/forest_admin_agent/utils/schema/action_fields.rb +76 -0
- data/lib/forest_admin_agent/utils/schema/forest_value_converter.rb +25 -6
- data/lib/forest_admin_agent/utils/schema/generator_action.rb +2 -1
- data/lib/forest_admin_agent/utils/schema/generator_action_field_widget.rb +261 -0
- data/lib/forest_admin_agent/utils/schema/schema_emitter.rb +1 -1
- data/lib/forest_admin_agent/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bec92ea32b9602067eec7ecaed2c92c63332c386c5d3d0fd25bf46b545005b8
|
4
|
+
data.tar.gz: 4e9ab47da288d943439ba1c593d58d9345cd720cfc4095b01ecac9f415e7eec1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a6ff92445703b96cce83d4603ea92ed20ef3c62db86e26a311ec65fb80d458c359522d7cfecba53b851595470fa7058297b9c78f8619bae1f022735bc9fa5eb8
|
7
|
+
data.tar.gz: 275d80a856cae78442d462f26126f9882ea30acccfc6c9b24bdbf82e09fad504aee259d0444d814c842a7dcce4691b9e462bc1eafc47e4a35a19ea4fa1fc8c39
|
@@ -37,6 +37,12 @@ module ForestAdminAgent
|
|
37
37
|
"#{path}/hooks/change",
|
38
38
|
proc { |args| handle_hook_request(args) }
|
39
39
|
)
|
40
|
+
add_route(
|
41
|
+
"#{route_name}_search",
|
42
|
+
'post',
|
43
|
+
"#{path}/hooks/search",
|
44
|
+
proc { |args| handle_hook_request(args) }
|
45
|
+
)
|
40
46
|
self
|
41
47
|
end
|
42
48
|
|
@@ -73,6 +79,8 @@ module ForestAdminAgent
|
|
73
79
|
forest_fields = args.dig(:params, :data, :attributes, :fields)
|
74
80
|
data = (Schema::ForestValueConverter.make_form_data_from_fields(@datasource, forest_fields) if forest_fields)
|
75
81
|
filter = get_record_selection(args)
|
82
|
+
search_values = {}
|
83
|
+
forest_fields&.each { |field| search_values[field['field']] = field['searchValue'] }
|
76
84
|
|
77
85
|
fields = @collection.get_form(
|
78
86
|
@caller,
|
@@ -81,8 +89,8 @@ module ForestAdminAgent
|
|
81
89
|
filter,
|
82
90
|
{
|
83
91
|
change_field: args.dig(:params, :data, :attributes, :changed_field),
|
84
|
-
search_field:
|
85
|
-
search_values:
|
92
|
+
search_field: args.dig(:params, :data, :attributes, :search_field),
|
93
|
+
search_values: search_values,
|
86
94
|
includeHiddenFields: false
|
87
95
|
}
|
88
96
|
)
|
@@ -21,6 +21,82 @@ module ForestAdminAgent
|
|
21
21
|
def self.file_list_field?(field)
|
22
22
|
field&.type == 'FileList'
|
23
23
|
end
|
24
|
+
|
25
|
+
def self.dropdown_field?(field)
|
26
|
+
field&.widget == 'Dropdown'
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.radio_group_field?(field)
|
30
|
+
field&.widget == 'RadioGroup'
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.checkbox_group_field?(field)
|
34
|
+
field&.widget == 'CheckboxGroup'
|
35
|
+
end
|
36
|
+
|
37
|
+
def self.checkbox_field?(field)
|
38
|
+
field&.widget == 'Checkbox'
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.text_input_field?(field)
|
42
|
+
field&.widget == 'TextInput'
|
43
|
+
end
|
44
|
+
|
45
|
+
def self.date_picker_field?(field)
|
46
|
+
field&.widget == 'DatePicker'
|
47
|
+
end
|
48
|
+
|
49
|
+
def self.file_picker_field?(field)
|
50
|
+
field&.widget == 'FilePicker'
|
51
|
+
end
|
52
|
+
|
53
|
+
def self.text_input_list_field?(field)
|
54
|
+
field&.widget == 'TextInputList'
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.text_area_field?(field)
|
58
|
+
field&.widget == 'TextArea'
|
59
|
+
end
|
60
|
+
|
61
|
+
def self.rich_text_field?(field)
|
62
|
+
field&.widget == 'RichText'
|
63
|
+
end
|
64
|
+
|
65
|
+
def self.number_input_field?(field)
|
66
|
+
field&.widget == 'NumberInput'
|
67
|
+
end
|
68
|
+
|
69
|
+
def self.color_picker_field?(field)
|
70
|
+
field&.widget == 'ColorPicker'
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.number_input_list_field?(field)
|
74
|
+
field&.widget == 'NumberInputList'
|
75
|
+
end
|
76
|
+
|
77
|
+
def self.currency_input_field?(field)
|
78
|
+
field&.widget == 'CurrencyInput'
|
79
|
+
end
|
80
|
+
|
81
|
+
def self.user_dropdown_field?(field)
|
82
|
+
field&.widget == 'UserDropdown'
|
83
|
+
end
|
84
|
+
|
85
|
+
def self.json_editor_field?(field)
|
86
|
+
field&.widget == 'JsonEditor'
|
87
|
+
end
|
88
|
+
|
89
|
+
def self.address_autocomplete_field?(field)
|
90
|
+
field&.widget == 'AddressAutocomplete'
|
91
|
+
end
|
92
|
+
|
93
|
+
def self.time_picker_field?(field)
|
94
|
+
field&.widget == 'TimePicker'
|
95
|
+
end
|
96
|
+
|
97
|
+
def self.widget?(field)
|
98
|
+
!field&.widget.nil?
|
99
|
+
end
|
24
100
|
end
|
25
101
|
end
|
26
102
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'base64'
|
2
|
+
|
1
3
|
module ForestAdminAgent
|
2
4
|
module Utils
|
3
5
|
module Schema
|
@@ -86,19 +88,36 @@ module ForestAdminAgent
|
|
86
88
|
|
87
89
|
return field.value&.join('|') if ActionFields.collection_field?(field)
|
88
90
|
|
89
|
-
|
90
|
-
|
91
|
-
|
91
|
+
return make_data_uri(field.value) if ActionFields.file_field?(field)
|
92
|
+
|
93
|
+
return value.map { |f| make_data_uri(f) } if ActionFields.file_list_field?(field)
|
92
94
|
|
93
95
|
field.value
|
94
96
|
end
|
95
97
|
|
96
98
|
def self.make_data_uri(file)
|
97
|
-
|
99
|
+
return if file.nil?
|
100
|
+
|
101
|
+
mime_type = `file --b --mime-type #{file.path}`.strip
|
102
|
+
value = Base64.strict_encode64(File.read(file.path))
|
103
|
+
|
104
|
+
"data:#{mime_type};base64,#{value}"
|
98
105
|
end
|
99
106
|
|
100
|
-
def self.parse_data_uri(
|
101
|
-
|
107
|
+
def self.parse_data_uri(data_uri)
|
108
|
+
return if data_uri.nil?
|
109
|
+
|
110
|
+
header, data = data_uri[5, data_uri.size].split(',')
|
111
|
+
mime_type, *media_types = header.split(';')
|
112
|
+
result = { 'mime_type' => mime_type, 'buffer' => Base64.strict_decode64(data) }
|
113
|
+
|
114
|
+
media_types.each do |media_type|
|
115
|
+
if (index = media_type.index('='))
|
116
|
+
result[media_type[0, index]] = CGI.unescape(media_type[index + 1, media_type.size])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
result
|
102
121
|
end
|
103
122
|
end
|
104
123
|
end
|
@@ -52,7 +52,8 @@ module ForestAdminAgent
|
|
52
52
|
isRequired: field.is_required,
|
53
53
|
isReadOnly: field.is_read_only,
|
54
54
|
field: field.label,
|
55
|
-
value: ForestValueConverter.value_to_forest(field)
|
55
|
+
value: ForestValueConverter.value_to_forest(field),
|
56
|
+
widgetEdit: GeneratorActionFieldWidget.build_widget_options(field)
|
56
57
|
}
|
57
58
|
|
58
59
|
output[:hook] = 'changeHook' if field.respond_to?(:watch_changes) && field.watch_changes
|
@@ -0,0 +1,261 @@
|
|
1
|
+
module ForestAdminAgent
|
2
|
+
module Utils
|
3
|
+
module Schema
|
4
|
+
class GeneratorActionFieldWidget
|
5
|
+
include ForestAdminDatasourceToolkit::Exceptions
|
6
|
+
|
7
|
+
def self.build_widget_options(field)
|
8
|
+
return if !ActionFields.widget?(field) || %w[Collection Enum EnumList].include?(field.type)
|
9
|
+
|
10
|
+
return build_dropdown_widget_edit(field) if ActionFields.dropdown_field?(field)
|
11
|
+
|
12
|
+
return build_radio_group_widget_edit(field) if ActionFields.radio_group_field?(field)
|
13
|
+
|
14
|
+
return build_checkbox_group_widget_edit(field) if ActionFields.checkbox_group_field?(field)
|
15
|
+
|
16
|
+
return build_checkbox_widget_edit(field) if ActionFields.checkbox_field?(field)
|
17
|
+
|
18
|
+
return build_text_input_widget_edit(field) if ActionFields.text_input_field?(field)
|
19
|
+
|
20
|
+
return build_date_picker_widget_edit(field) if ActionFields.date_picker_field?(field)
|
21
|
+
|
22
|
+
return build_text_input_list_widget_edit(field) if ActionFields.text_input_list_field?(field)
|
23
|
+
|
24
|
+
return build_text_area_widget_edit(field) if ActionFields.text_area_field?(field)
|
25
|
+
|
26
|
+
return build_rich_text_widget_edit(field) if ActionFields.rich_text_field?(field)
|
27
|
+
|
28
|
+
return build_number_input_widget_edit(field) if ActionFields.number_input_field?(field)
|
29
|
+
|
30
|
+
return build_color_picker_widget_edit(field) if ActionFields.color_picker_field?(field)
|
31
|
+
|
32
|
+
return build_number_input_list_widget_edit(field) if ActionFields.number_input_list_field?(field)
|
33
|
+
|
34
|
+
return build_currency_input_widget_edit(field) if ActionFields.currency_input_field?(field)
|
35
|
+
|
36
|
+
return build_user_dropdown_widget_edit(field) if ActionFields.user_dropdown_field?(field)
|
37
|
+
|
38
|
+
return build_time_picker_widget_edit(field) if ActionFields.time_picker_field?(field)
|
39
|
+
|
40
|
+
return build_json_editor_widget_edit(field) if ActionFields.json_editor_field?(field)
|
41
|
+
|
42
|
+
return build_file_picker_widget_edit(field) if ActionFields.file_picker_field?(field)
|
43
|
+
|
44
|
+
return build_address_autocomplete_widget_edit(field) if ActionFields.address_autocomplete_field?(field)
|
45
|
+
|
46
|
+
raise ForestException, "Unsupported widget type: #{field&.widget}"
|
47
|
+
end
|
48
|
+
|
49
|
+
class << self
|
50
|
+
private
|
51
|
+
|
52
|
+
def build_dropdown_widget_edit(field)
|
53
|
+
{
|
54
|
+
name: 'dropdown',
|
55
|
+
parameters: {
|
56
|
+
searchType: field.search == 'dynamic' ? 'dynamic' : nil,
|
57
|
+
isSearchable: %w[static dynamic].include?(field.search),
|
58
|
+
placeholder: field.placeholder,
|
59
|
+
static: { options: field.options || [] }
|
60
|
+
}
|
61
|
+
}
|
62
|
+
end
|
63
|
+
|
64
|
+
def build_radio_group_widget_edit(field)
|
65
|
+
{
|
66
|
+
name: 'radio button',
|
67
|
+
parameters: {
|
68
|
+
static: {
|
69
|
+
options: field.options || []
|
70
|
+
}
|
71
|
+
}
|
72
|
+
}
|
73
|
+
end
|
74
|
+
|
75
|
+
def build_checkbox_group_widget_edit(field)
|
76
|
+
{
|
77
|
+
name: 'checkboxes',
|
78
|
+
parameters: {
|
79
|
+
static: {
|
80
|
+
options: field.options || []
|
81
|
+
}
|
82
|
+
}
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
def build_checkbox_widget_edit(_field)
|
87
|
+
{
|
88
|
+
name: 'boolean editor',
|
89
|
+
parameters: {}
|
90
|
+
}
|
91
|
+
end
|
92
|
+
|
93
|
+
def build_text_input_widget_edit(field)
|
94
|
+
{
|
95
|
+
name: 'text editor',
|
96
|
+
parameters: {
|
97
|
+
placeholder: field.placeholder
|
98
|
+
}
|
99
|
+
}
|
100
|
+
end
|
101
|
+
|
102
|
+
def build_date_picker_widget_edit(field)
|
103
|
+
{
|
104
|
+
name: 'date editor',
|
105
|
+
parameters: {
|
106
|
+
format: field.format,
|
107
|
+
placeholder: field.placeholder,
|
108
|
+
minDate: field.min.is_a?(Date) ? field.min.iso8601 : nil,
|
109
|
+
maxDate: field.max.is_a?(Date) ? field.max.iso8601 : nil
|
110
|
+
}
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
def build_text_input_list_widget_edit(field)
|
115
|
+
{
|
116
|
+
name: 'input array',
|
117
|
+
parameters: {
|
118
|
+
placeholder: field.placeholder,
|
119
|
+
allowDuplicate: field.allow_duplicates,
|
120
|
+
allowEmptyValue: field.allow_empty_values,
|
121
|
+
enableReorder: field.enable_reorder
|
122
|
+
}
|
123
|
+
}
|
124
|
+
end
|
125
|
+
|
126
|
+
def build_text_area_widget_edit(field)
|
127
|
+
{
|
128
|
+
name: 'text area editor',
|
129
|
+
parameters: {
|
130
|
+
placeholder: field.placeholder,
|
131
|
+
rows: valid_number?(field.rows) && field.rows.positive? ? field.rows.round : nil
|
132
|
+
}
|
133
|
+
}
|
134
|
+
end
|
135
|
+
|
136
|
+
def build_rich_text_widget_edit(field)
|
137
|
+
{
|
138
|
+
name: 'rich text',
|
139
|
+
parameters: {
|
140
|
+
placeholder: field.placeholder
|
141
|
+
}
|
142
|
+
}
|
143
|
+
end
|
144
|
+
|
145
|
+
def build_number_input_widget_edit(field)
|
146
|
+
{
|
147
|
+
name: 'number input',
|
148
|
+
parameters: {
|
149
|
+
placeholder: field.placeholder,
|
150
|
+
min: valid_number?(field.min) ? field.min : nil,
|
151
|
+
max: valid_number?(field.max) ? field.max : nil,
|
152
|
+
step: valid_number?(field.step) ? field.step : nil
|
153
|
+
}
|
154
|
+
}
|
155
|
+
end
|
156
|
+
|
157
|
+
def build_color_picker_widget_edit(field)
|
158
|
+
{
|
159
|
+
name: 'color editor',
|
160
|
+
parameters: {
|
161
|
+
placeholder: field.placeholder,
|
162
|
+
enableOpacity: field.enable_opacity,
|
163
|
+
quickPalette: field.quick_palette
|
164
|
+
}
|
165
|
+
}
|
166
|
+
end
|
167
|
+
|
168
|
+
def build_number_input_list_widget_edit(field)
|
169
|
+
{
|
170
|
+
name: 'input array',
|
171
|
+
parameters: {
|
172
|
+
placeholder: field.placeholder,
|
173
|
+
allowDuplicate: field.allow_duplicates.nil? ? false : field.allow_duplicates,
|
174
|
+
enableReorder: field.enable_reorder.nil? ? true : field.enable_reorder,
|
175
|
+
min: valid_number?(field.min) ? field.min : nil,
|
176
|
+
max: valid_number?(field.max) ? field.max : nil,
|
177
|
+
step: valid_number?(field.step) ? field.step : nil
|
178
|
+
}
|
179
|
+
}
|
180
|
+
end
|
181
|
+
|
182
|
+
def build_currency_input_widget_edit(field)
|
183
|
+
{
|
184
|
+
name: 'price editor',
|
185
|
+
parameters: {
|
186
|
+
placeholder: field.placeholder,
|
187
|
+
min: valid_number?(field.min) ? field.min : nil,
|
188
|
+
max: valid_number?(field.max) ? field.max : nil,
|
189
|
+
step: valid_number?(field.step) ? field.step : nil,
|
190
|
+
currency: field.currency.is_a?(String) && field.currency.length == 3 ? field.currency.upcase : nil,
|
191
|
+
base: map_currency_base(field.base)
|
192
|
+
}
|
193
|
+
}
|
194
|
+
end
|
195
|
+
|
196
|
+
def build_time_picker_widget_edit(_field)
|
197
|
+
{
|
198
|
+
name: 'time editor',
|
199
|
+
parameters: {}
|
200
|
+
}
|
201
|
+
end
|
202
|
+
|
203
|
+
def build_json_editor_widget_edit(_field)
|
204
|
+
{
|
205
|
+
name: 'json code editor',
|
206
|
+
parameters: {}
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
def build_file_picker_widget_edit(field)
|
211
|
+
{
|
212
|
+
name: 'file picker',
|
213
|
+
parameters: {
|
214
|
+
prefix: nil,
|
215
|
+
filesExtensions: field.extensions,
|
216
|
+
filesSizeLimit: field.max_size_mb,
|
217
|
+
filesCountLimit: field.max_count
|
218
|
+
}
|
219
|
+
}
|
220
|
+
end
|
221
|
+
|
222
|
+
def build_address_autocomplete_widget_edit(field)
|
223
|
+
{
|
224
|
+
name: 'address editor',
|
225
|
+
parameters: {
|
226
|
+
placeholder: field.placeholder
|
227
|
+
}
|
228
|
+
}
|
229
|
+
end
|
230
|
+
|
231
|
+
def build_user_dropdown_widget_edit(field)
|
232
|
+
{
|
233
|
+
name: 'assignee editor',
|
234
|
+
parameters: {
|
235
|
+
placeholder: field.placeholder
|
236
|
+
}
|
237
|
+
}
|
238
|
+
end
|
239
|
+
|
240
|
+
def valid_number?(value)
|
241
|
+
if value.is_a? String
|
242
|
+
begin
|
243
|
+
return true if value.to_f
|
244
|
+
rescue StandardError
|
245
|
+
false
|
246
|
+
end
|
247
|
+
end
|
248
|
+
|
249
|
+
value.is_a? Numeric
|
250
|
+
end
|
251
|
+
|
252
|
+
def map_currency_base(base)
|
253
|
+
return 'Cent' if %w[cents cent].include?(base.downcase)
|
254
|
+
|
255
|
+
'Unit'
|
256
|
+
end
|
257
|
+
end
|
258
|
+
end
|
259
|
+
end
|
260
|
+
end
|
261
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: forest_admin_agent
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.pre.beta.
|
4
|
+
version: 1.0.0.pre.beta.52
|
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-
|
12
|
+
date: 2024-06-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
@@ -283,6 +283,7 @@ files:
|
|
283
283
|
- lib/forest_admin_agent/utils/schema/frontend_filterable.rb
|
284
284
|
- lib/forest_admin_agent/utils/schema/frontend_validation_utils.rb
|
285
285
|
- lib/forest_admin_agent/utils/schema/generator_action.rb
|
286
|
+
- lib/forest_admin_agent/utils/schema/generator_action_field_widget.rb
|
286
287
|
- lib/forest_admin_agent/utils/schema/generator_collection.rb
|
287
288
|
- lib/forest_admin_agent/utils/schema/generator_field.rb
|
288
289
|
- lib/forest_admin_agent/utils/schema/schema_emitter.rb
|