active_scaffold 4.2.3 → 4.3.0
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/CHANGELOG.rdoc +16 -1
- data/README.md +108 -7
- data/app/assets/javascripts/{jquery → active_scaffold}/active_scaffold.js +759 -762
- data/app/assets/javascripts/{jquery/date_picker_bridge.js.erb → active_scaffold/date_picker_bridge.js} +0 -3
- data/app/assets/javascripts/active_scaffold/load.js +102 -0
- data/app/assets/javascripts/active_scaffold.js.erb +3 -27
- data/app/assets/stylesheets/active_scaffold/_colours.scss +330 -0
- data/app/assets/stylesheets/active_scaffold/_images.scss +65 -0
- data/app/assets/stylesheets/{active_scaffold_layout.scss → active_scaffold/_layout.scss} +14 -0
- data/app/assets/stylesheets/active_scaffold/_variables.scss +194 -0
- data/app/assets/stylesheets/active_scaffold/core.scss +15 -0
- data/app/assets/stylesheets/active_scaffold.scss.erb +16 -0
- data/app/views/active_scaffold_overrides/_field_search_columns.html.erb +8 -0
- data/app/views/active_scaffold_overrides/_form.html.erb +8 -0
- data/app/views/active_scaffold_overrides/_form_association.html.erb +3 -1
- data/app/views/active_scaffold_overrides/_form_association_record.html.erb +4 -2
- data/app/views/active_scaffold_overrides/_show_association.html.erb +2 -1
- data/app/views/active_scaffold_overrides/_show_association_horizontal.html.erb +2 -2
- data/app/views/active_scaffold_overrides/_show_association_vertical.html.erb +1 -1
- data/app/views/active_scaffold_overrides/edit_associated.js.erb +10 -8
- data/lib/active_scaffold/actions/core.rb +34 -3
- data/lib/active_scaffold/assets/css_deps_generator.rb +42 -0
- data/lib/active_scaffold/assets/jquery_ui_manifest.rb +77 -0
- data/lib/active_scaffold/assets/jquery_ui_theme_generator.rb +102 -0
- data/lib/active_scaffold/assets.rb +109 -0
- data/lib/active_scaffold/attribute_params.rb +11 -2
- data/lib/active_scaffold/bridges/active_storage/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/chosen.rb +1 -1
- data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/file_column/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/paperclip/form_ui.rb +1 -1
- data/lib/active_scaffold/bridges/record_select/helpers.rb +1 -1
- data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +1 -0
- data/lib/active_scaffold/bridges/tiny_mce.rb +6 -1
- data/lib/active_scaffold/bridges.rb +7 -0
- data/lib/active_scaffold/config/core.rb +7 -3
- data/lib/active_scaffold/constraints.rb +1 -1
- data/lib/active_scaffold/data_structures/action_columns.rb +66 -0
- data/lib/active_scaffold/data_structures/bridge.rb +2 -0
- data/lib/active_scaffold/data_structures/column.rb +3 -0
- data/lib/active_scaffold/engine.rb +40 -0
- data/lib/active_scaffold/finder.rb +1 -1
- data/lib/active_scaffold/helpers/assets_helpers.rb +39 -0
- data/lib/active_scaffold/helpers/controller_helpers.rb +1 -1
- data/lib/active_scaffold/helpers/form_column_helpers.rb +57 -532
- data/lib/active_scaffold/helpers/form_ui_helpers.rb +530 -0
- data/lib/active_scaffold/helpers/human_condition_helpers.rb +1 -0
- data/lib/active_scaffold/helpers/list_column_helpers.rb +31 -11
- data/lib/active_scaffold/helpers/search_column_helpers.rb +5 -12
- data/lib/active_scaffold/helpers/show_column_helpers.rb +4 -2
- data/lib/active_scaffold/helpers/view_helpers.rb +12 -0
- data/lib/active_scaffold/railties/tasks.rake +10 -0
- data/lib/active_scaffold/testing/assert_embedded_load.rb +33 -0
- data/lib/active_scaffold/version.rb +2 -2
- data/lib/active_scaffold.rb +7 -2
- data/lib/tasks/active_scaffold/assets.rake +42 -0
- data/lib/tasks/bundle.rake +25 -0
- data/vendor/assets/stylesheets/{jquery-ui-theme.css.erb → jquery-ui-theme.css} +17 -17
- metadata +26 -28
- data/app/assets/stylesheets/active_scaffold.scss +0 -424
- data/app/assets/stylesheets/active_scaffold_extensions.css.erb +0 -2
- data/app/assets/stylesheets/active_scaffold_images.scss +0 -65
- data/app/assets/stylesheets/active_scaffold_jquery_ui.css.erb +0 -13
- /data/app/assets/javascripts/{jquery → active_scaffold}/active_scaffold_chosen.js +0 -0
- /data/app/assets/javascripts/{jquery → active_scaffold}/draggable_lists.js +0 -0
- /data/app/assets/javascripts/{jquery → active_scaffold}/jquery.editinplace.js +0 -0
- /data/app/assets/javascripts/{jquery → active_scaffold}/tiny_mce_bridge.js +0 -0
|
@@ -6,9 +6,9 @@ module ActiveScaffold
|
|
|
6
6
|
module FormColumnHelpers
|
|
7
7
|
# This method decides which input to use for the given column.
|
|
8
8
|
# It does not do any rendering. It only decides which method is responsible for rendering.
|
|
9
|
-
def active_scaffold_input_for(column, scope = nil, options = nil)
|
|
9
|
+
def active_scaffold_input_for(column, scope = nil, options = nil, form_columns: nil)
|
|
10
10
|
options ||= active_scaffold_input_options(column, scope)
|
|
11
|
-
options = update_columns_options(column, scope, options)
|
|
11
|
+
options = update_columns_options(column, scope, options, form_columns: form_columns)
|
|
12
12
|
active_scaffold_render_input(column, options)
|
|
13
13
|
end
|
|
14
14
|
|
|
@@ -49,12 +49,10 @@ module ActiveScaffold
|
|
|
49
49
|
text_field(:record, column.name, options.merge(column.options).except(:format))
|
|
50
50
|
end
|
|
51
51
|
rescue StandardError => e
|
|
52
|
-
|
|
53
|
-
ActiveScaffold.log_exception(e, message)
|
|
54
|
-
raise e.class, "#{e.message} -- #{message}", e.backtrace
|
|
52
|
+
handle_exception_on_column(e, column, record)
|
|
55
53
|
end
|
|
56
54
|
|
|
57
|
-
def active_scaffold_render_subform_column(column, scope, crud_type, readonly, add_class = false, record = nil) # rubocop:disable Metrics/ParameterLists
|
|
55
|
+
def active_scaffold_render_subform_column(column, scope, crud_type, readonly, add_class = false, record = nil, form_columns: nil) # rubocop:disable Metrics/ParameterLists
|
|
58
56
|
if add_class
|
|
59
57
|
col_class = []
|
|
60
58
|
col_class << 'required' if column.required?(action_for_validation(record))
|
|
@@ -67,7 +65,7 @@ module ActiveScaffold
|
|
|
67
65
|
form_attribute(column, record, scope, true, col_class)
|
|
68
66
|
else
|
|
69
67
|
renders_as = column_renders_as(column)
|
|
70
|
-
html = render_column(column, record, renders_as, scope, only_value: false, col_class: col_class)
|
|
68
|
+
html = render_column(column, record, renders_as, scope, only_value: false, col_class: col_class, form_columns: form_columns)
|
|
71
69
|
html = content_tag(:div, html, active_scaffold_subform_attributes(column)) if renders_as == :subform
|
|
72
70
|
html
|
|
73
71
|
end
|
|
@@ -195,18 +193,23 @@ module ActiveScaffold
|
|
|
195
193
|
end
|
|
196
194
|
end
|
|
197
195
|
|
|
198
|
-
def render_column(column, record, renders_as, scope = nil, only_value: false, col_class: nil, **subform_locals)
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
196
|
+
def render_column(column, record, renders_as, scope = nil, only_value: false, col_class: nil, form_columns: nil, **subform_locals)
|
|
197
|
+
hide_column, clear = form_column_is_hidden?(column, record, scope)
|
|
198
|
+
if hide_column
|
|
199
|
+
if clear
|
|
200
|
+
form_hidden_attribute(column, record, scope, true)
|
|
201
|
+
else
|
|
202
|
+
# creates an element that can be replaced by the update_columns routine,
|
|
203
|
+
# but will not affect the value of the submitted form in this state:
|
|
204
|
+
# <dl><input type="hidden" class="<%= column.name %>-input"></dl>
|
|
205
|
+
content_tag :dl, style: 'display: none' do
|
|
206
|
+
hidden_field_tag(nil, nil, class: "#{column.name}-input")
|
|
207
|
+
end
|
|
205
208
|
end
|
|
206
209
|
elsif (partial = override_form_field_partial(column))
|
|
207
|
-
render partial, column: column, only_value: only_value, scope: scope, col_class: col_class, record: record
|
|
210
|
+
render partial, column: column, only_value: only_value, scope: scope, col_class: col_class, record: record, form_columns: form_columns
|
|
208
211
|
elsif renders_as == :field || override_form_field?(column)
|
|
209
|
-
form_attribute(column, record, scope, only_value, col_class)
|
|
212
|
+
form_attribute(column, record, scope, only_value, col_class, form_columns: form_columns)
|
|
210
213
|
elsif renders_as == :subform
|
|
211
214
|
render 'form_association', subform_locals.slice(:tabbed_by, :tab_value, :tab_id).merge(column: column, scope: scope, parent_record: record)
|
|
212
215
|
else
|
|
@@ -214,14 +217,23 @@ module ActiveScaffold
|
|
|
214
217
|
end
|
|
215
218
|
end
|
|
216
219
|
|
|
217
|
-
def form_column_is_hidden?(column, record, scope = nil)
|
|
218
|
-
if column.
|
|
219
|
-
column.hide_form_column_if
|
|
220
|
-
|
|
221
|
-
record.send(column.hide_form_column_if)
|
|
220
|
+
def form_column_is_hidden?(column, record, scope = nil) # rubocop:disable Naming/PredicateMethod
|
|
221
|
+
if column.clear_form_column_if.nil?
|
|
222
|
+
condition_to_hide = column.hide_form_column_if
|
|
223
|
+
clear = false
|
|
222
224
|
else
|
|
223
|
-
column.
|
|
224
|
-
|
|
225
|
+
condition_to_hide = column.clear_form_column_if
|
|
226
|
+
clear = true
|
|
227
|
+
end
|
|
228
|
+
hide =
|
|
229
|
+
if condition_to_hide.respond_to?(:call)
|
|
230
|
+
condition_to_hide.call(record, column, scope)
|
|
231
|
+
elsif condition_to_hide.is_a?(Symbol)
|
|
232
|
+
record.send(condition_to_hide)
|
|
233
|
+
else
|
|
234
|
+
condition_to_hide
|
|
235
|
+
end
|
|
236
|
+
[hide, clear]
|
|
225
237
|
end
|
|
226
238
|
|
|
227
239
|
def column_description(column, record, scope = nil)
|
|
@@ -229,7 +241,7 @@ module ActiveScaffold
|
|
|
229
241
|
content_tag(:span, h(desc) + content_tag(:span, nil, class: 'close'), class: 'description') if desc.present?
|
|
230
242
|
end
|
|
231
243
|
|
|
232
|
-
def form_attribute(column, record, scope = nil, only_value = false, col_class = nil)
|
|
244
|
+
def form_attribute(column, record, scope = nil, only_value = false, col_class = nil, form_columns: nil)
|
|
233
245
|
column_options = active_scaffold_input_options(column, scope, object: record)
|
|
234
246
|
collapsible_id = column_options.delete :collapsible_id
|
|
235
247
|
attributes = field_attributes(column, record)
|
|
@@ -243,7 +255,7 @@ module ActiveScaffold
|
|
|
243
255
|
field << hidden_field(:record, method, column_options)
|
|
244
256
|
end
|
|
245
257
|
else
|
|
246
|
-
field = active_scaffold_input_for column, scope, column_options
|
|
258
|
+
field = active_scaffold_input_for column, scope, column_options, form_columns: form_columns
|
|
247
259
|
end
|
|
248
260
|
if field
|
|
249
261
|
field << loading_indicator_tag(action: :render_field, id: params[:id]) if column.update_columns
|
|
@@ -270,30 +282,41 @@ module ActiveScaffold
|
|
|
270
282
|
column.label unless hidden
|
|
271
283
|
end
|
|
272
284
|
|
|
273
|
-
def form_hidden_attribute(column, record, scope = nil)
|
|
285
|
+
def form_hidden_attribute(column, record, scope = nil, clear = false)
|
|
274
286
|
content_tag :dl, style: 'display: none' do
|
|
275
287
|
content_tag(:dt, '') <<
|
|
276
|
-
content_tag(:dd, form_hidden_field(column, record, scope))
|
|
288
|
+
content_tag(:dd, form_hidden_field(column, record, scope, clear))
|
|
277
289
|
end
|
|
278
290
|
end
|
|
279
291
|
|
|
280
|
-
def form_hidden_field(column, record, scope)
|
|
292
|
+
def form_hidden_field(column, record, scope, clear = false)
|
|
281
293
|
options = active_scaffold_input_options(column, scope)
|
|
294
|
+
value = record.send(column.name) unless clear
|
|
282
295
|
if column.association&.collection?
|
|
283
|
-
|
|
284
|
-
if
|
|
296
|
+
options[:name] += '[]'
|
|
297
|
+
if value.blank?
|
|
285
298
|
hidden_field_tag options[:name], '', options
|
|
286
299
|
else
|
|
287
|
-
|
|
288
|
-
fields = associated.map do |r|
|
|
300
|
+
fields = value.map do |r|
|
|
289
301
|
hidden_field_tag options[:name], r.id, options.merge(id: options[:id] + "_#{r.id}")
|
|
290
302
|
end
|
|
291
303
|
safe_join fields, ''
|
|
292
304
|
end
|
|
293
305
|
elsif column.association
|
|
294
|
-
hidden_field_tag options[:name],
|
|
306
|
+
hidden_field_tag options[:name], value&.id, options
|
|
295
307
|
else
|
|
296
|
-
|
|
308
|
+
options[:name] += '[]' if active_scaffold_column_expect_array?(column)
|
|
309
|
+
hidden_field_tag options[:name], value, options
|
|
310
|
+
end
|
|
311
|
+
end
|
|
312
|
+
|
|
313
|
+
def active_scaffold_column_expect_array?(column)
|
|
314
|
+
ui_options = column.form_ui_options || column.options
|
|
315
|
+
case column.form_ui
|
|
316
|
+
when :select
|
|
317
|
+
column.association&.collection? || ui_options[:multiple]
|
|
318
|
+
when :select_multiple, :checkboxes, :draggable
|
|
319
|
+
true
|
|
297
320
|
end
|
|
298
321
|
end
|
|
299
322
|
|
|
@@ -330,504 +353,6 @@ module ActiveScaffold
|
|
|
330
353
|
value
|
|
331
354
|
end
|
|
332
355
|
|
|
333
|
-
##
|
|
334
|
-
## Form input methods
|
|
335
|
-
##
|
|
336
|
-
|
|
337
|
-
def active_scaffold_grouped_options(column, select_options, optgroup)
|
|
338
|
-
group_column = active_scaffold_config_for(column.association.klass).columns[optgroup]
|
|
339
|
-
group_label = group_column.options[:label_method] if group_column
|
|
340
|
-
group_label ||= group_column&.association ? :to_label : :to_s
|
|
341
|
-
select_options.group_by(&optgroup.to_sym).collect do |group, options|
|
|
342
|
-
[group.send(group_label), options.collect { |r| [r.send(column.options[:label_method] || :to_label), r.id] }]
|
|
343
|
-
end
|
|
344
|
-
end
|
|
345
|
-
|
|
346
|
-
def active_scaffold_translate_select_options(options)
|
|
347
|
-
options[:include_blank] = as_(options[:include_blank].to_s) if options[:include_blank].is_a? Symbol
|
|
348
|
-
options[:prompt] = as_(options[:prompt].to_s) if options[:prompt].is_a? Symbol
|
|
349
|
-
options
|
|
350
|
-
end
|
|
351
|
-
|
|
352
|
-
def active_scaffold_select_name_with_multiple(options)
|
|
353
|
-
return if !options[:multiple] || options[:name].to_s.ends_with?('[]')
|
|
354
|
-
|
|
355
|
-
options[:name] = "#{options[:name]}[]"
|
|
356
|
-
end
|
|
357
|
-
|
|
358
|
-
def active_scaffold_input_singular_association(column, html_options, options = {}, ui_options: column.options)
|
|
359
|
-
record = html_options.delete(:object)
|
|
360
|
-
associated = html_options.include?(:associated) ? html_options.delete(:associated) : record.send(column.association.name)
|
|
361
|
-
|
|
362
|
-
helper_method = association_helper_method(column.association, :sorted_association_options_find)
|
|
363
|
-
select_options = send(helper_method, column.association, nil, record)
|
|
364
|
-
select_options.unshift(associated) if associated&.persisted? && select_options.exclude?(associated)
|
|
365
|
-
|
|
366
|
-
method = column.name
|
|
367
|
-
options.merge! selected: associated&.id, include_blank: as_(:_select_), object: record
|
|
368
|
-
|
|
369
|
-
html_options.merge!(ui_options[:html_options] || {})
|
|
370
|
-
options.merge!(ui_options)
|
|
371
|
-
html_options.delete(:multiple) # no point using multiple in a form for singular assoc, but may be set for field search
|
|
372
|
-
active_scaffold_translate_select_options(options)
|
|
373
|
-
|
|
374
|
-
html =
|
|
375
|
-
if (optgroup = options.delete(:optgroup))
|
|
376
|
-
select(:record, method, active_scaffold_grouped_options(column, select_options, optgroup), options, html_options)
|
|
377
|
-
else
|
|
378
|
-
collection_select(:record, method, select_options, :id, ui_options[:label_method] || :to_label, options, html_options)
|
|
379
|
-
end
|
|
380
|
-
html << active_scaffold_refresh_link(column, html_options, record, ui_options) if ui_options[:refresh_link]
|
|
381
|
-
html
|
|
382
|
-
end
|
|
383
|
-
|
|
384
|
-
def active_scaffold_new_record_klass(column, record, **options)
|
|
385
|
-
if column.association.polymorphic? && column.association.belongs_to?
|
|
386
|
-
type = record.send(column.association.foreign_type)
|
|
387
|
-
type_options = options[:types]
|
|
388
|
-
column.association.klass(record) if type.present? && (type_options.nil? || type_options.include?(type))
|
|
389
|
-
else
|
|
390
|
-
column.association.klass
|
|
391
|
-
end
|
|
392
|
-
end
|
|
393
|
-
|
|
394
|
-
def active_scaffold_add_new(column, record, html_options, ui_options: column.options, skip_link: false)
|
|
395
|
-
options = ui_options[:add_new] == true ? {} : ui_options[:add_new]
|
|
396
|
-
options[:mode] = :popup if column.association&.collection?
|
|
397
|
-
case options[:mode]
|
|
398
|
-
when nil, :subform
|
|
399
|
-
active_scaffold_new_record_subform(column, record, html_options, options: options, skip_link: skip_link)
|
|
400
|
-
when :popup
|
|
401
|
-
active_scaffold_new_record_popup(column, record, html_options, options: options) unless skip_link
|
|
402
|
-
else
|
|
403
|
-
raise ArgumentError, "unsupported mode for add_new: #{options[:mode].inspect}"
|
|
404
|
-
end
|
|
405
|
-
end
|
|
406
|
-
|
|
407
|
-
def active_scaffold_new_record_url_options(column, record)
|
|
408
|
-
if column.association.reverse
|
|
409
|
-
constraint = [record.id]
|
|
410
|
-
constraint.unshift record.class.name if column.association.reverse_association.polymorphic?
|
|
411
|
-
{embedded: {constraints: {column.association.reverse => constraint}}}
|
|
412
|
-
else
|
|
413
|
-
raise "can't add constraint to create new record with :popup, no reverse association for " \
|
|
414
|
-
"\"#{column.name}\" in #{column.association.klass}, add the reverse association " \
|
|
415
|
-
'or override active_scaffold_new_record_url_options helper.'
|
|
416
|
-
end
|
|
417
|
-
end
|
|
418
|
-
|
|
419
|
-
def active_scaffold_new_record_popup(column, record, html_options, options: {})
|
|
420
|
-
klass = send(override_helper_per_model(:active_scaffold_new_record_klass, record.class), column, record, **options)
|
|
421
|
-
klass = nil if options[:security_method] && !controller.send(options[:security_method])
|
|
422
|
-
klass = nil if klass && options[:security_method].nil? && !klass.authorized_for?(crud_type: :create)
|
|
423
|
-
return h('') unless klass
|
|
424
|
-
|
|
425
|
-
link_text = active_scaffold_add_new_text(options, :add_new_text, :add)
|
|
426
|
-
url_options_helper = override_helper_per_model(:active_scaffold_new_record_url_options, record.class)
|
|
427
|
-
url_options = send(url_options_helper, column, record)
|
|
428
|
-
url_options[:controller] ||= active_scaffold_controller_for(klass).controller_path
|
|
429
|
-
url_options[:action] ||= :new
|
|
430
|
-
url_options[:from_field] ||= html_options[:id]
|
|
431
|
-
url_options[:parent_model] ||= record.class.name
|
|
432
|
-
url_options[:parent_column] ||= column.name
|
|
433
|
-
url_options.reverse_merge! options[:url_options] if options[:url_options]
|
|
434
|
-
link_to(link_text, url_options, remote: true, data: {position: :popup}, class: 'as_action')
|
|
435
|
-
end
|
|
436
|
-
|
|
437
|
-
def active_scaffold_new_record_subform(column, record, html_options, options: {}, new_record_attributes: nil, locals: {}, skip_link: false)
|
|
438
|
-
klass = send(override_helper_per_model(:active_scaffold_new_record_klass, record.class), column, record, **options)
|
|
439
|
-
return content_tag(:div, '') unless klass
|
|
440
|
-
|
|
441
|
-
subform_attrs = active_scaffold_subform_attributes(column, nil, klass, ui_options: options)
|
|
442
|
-
if record.send(column.name)&.new_record?
|
|
443
|
-
new_record = record.send(column.name)
|
|
444
|
-
else
|
|
445
|
-
subform_attrs[:style] = 'display: none'
|
|
446
|
-
end
|
|
447
|
-
subform_attrs[:class] << ' optional'
|
|
448
|
-
scope = html_options[:name].scan(/record(.*)\[#{column.name}\]/).dig(0, 0)
|
|
449
|
-
new_record ||= klass.new(new_record_attributes)
|
|
450
|
-
locals = locals.reverse_merge(column: column, parent_record: record, associated: [], show_blank_record: new_record, scope: scope)
|
|
451
|
-
subform = render(partial: subform_partial_for_column(column, klass, ui_options: options), locals: locals)
|
|
452
|
-
if options[:hide_subgroups]
|
|
453
|
-
toggable_id = "#{sub_form_id(association: column.name, id: record.id || generated_id(record) || 99_999_999_999)}-div"
|
|
454
|
-
subform << link_to_visibility_toggle(toggable_id, default_visible: false)
|
|
455
|
-
end
|
|
456
|
-
html = content_tag(:div, subform, subform_attrs)
|
|
457
|
-
return html if skip_link
|
|
458
|
-
|
|
459
|
-
html << active_scaffold_show_new_subform_link(column, record, html_options[:id], subform_attrs[:id], options: options)
|
|
460
|
-
end
|
|
461
|
-
|
|
462
|
-
def active_scaffold_add_new_text(options, key, default)
|
|
463
|
-
text = options[key] unless options == true
|
|
464
|
-
return text if text.is_a? String
|
|
465
|
-
|
|
466
|
-
as_(text || default)
|
|
467
|
-
end
|
|
468
|
-
|
|
469
|
-
def active_scaffold_show_new_subform_link(column, record, select_id, subform_id, options: {})
|
|
470
|
-
add_existing = active_scaffold_add_new_text(options, :add_existing_text, :add_existing)
|
|
471
|
-
create_new = active_scaffold_add_new_text(options, :add_new_text, :create_new)
|
|
472
|
-
data = {select_id: select_id, subform_id: subform_id, subform_text: add_existing, select_text: create_new}
|
|
473
|
-
label = data[record.send(column.name)&.new_record? ? :subform_text : :select_text]
|
|
474
|
-
link_to(label, '#', data: data, class: 'show-new-subform')
|
|
475
|
-
end
|
|
476
|
-
|
|
477
|
-
def active_scaffold_file_with_content(column, options, content, remove_file_prefix, controls_class, ui_options: column.options)
|
|
478
|
-
options = active_scaffold_input_text_options(options.merge(ui_options))
|
|
479
|
-
options[:style] = 'display: none' if content
|
|
480
|
-
field = file_field(:record, column.name, options)
|
|
481
|
-
|
|
482
|
-
if content
|
|
483
|
-
content = [content, ' | ']
|
|
484
|
-
content << yield if block_given?
|
|
485
|
-
object_name, method = options[:name].split(/\[(#{column.name})\]/)
|
|
486
|
-
method.sub!(/#{column.name}/, "#{remove_file_prefix}\\0")
|
|
487
|
-
content << hidden_field(object_name, method, value: 'false', class: 'remove_file')
|
|
488
|
-
active_scaffold_file_with_remove_link(safe_join(content), options, controls_class) { field }
|
|
489
|
-
else
|
|
490
|
-
field
|
|
491
|
-
end
|
|
492
|
-
end
|
|
493
|
-
|
|
494
|
-
def active_scaffold_file_with_remove_link(content, options, controls_class, link_key = nil)
|
|
495
|
-
required = options.delete(:required)
|
|
496
|
-
link_key ||= options[:multiple] ? :remove_files : :remove_file
|
|
497
|
-
content_tag(:div, class: "#{controls_class} file-input-controls", data: {required: required}) do
|
|
498
|
-
content_line = content_tag(:div) do
|
|
499
|
-
safe_join [content, content_tag(:a, as_(link_key), href: '#', class: 'remove-file-btn')]
|
|
500
|
-
end
|
|
501
|
-
content_line << yield if block_given?
|
|
502
|
-
content_line
|
|
503
|
-
end
|
|
504
|
-
end
|
|
505
|
-
|
|
506
|
-
def active_scaffold_refresh_link(column, html_options, record, ui_options = {})
|
|
507
|
-
link_options = {object: record, data: {field_selector: ui_options[:field_selector] || "##{html_options[:id]}"}}
|
|
508
|
-
if html_options['data-update_url']
|
|
509
|
-
link_options['data-update_send_form'] = html_options['data-update_send_form']
|
|
510
|
-
link_options['data-update_send_form_selector'] = html_options['data-update_send_form_selector']
|
|
511
|
-
else
|
|
512
|
-
scope = html_options[:name].scan(/^record((\[[^\]]*\])*)\[#{column.name}\]/).dig(0, 0) if html_options[:name]
|
|
513
|
-
link_options = update_columns_options(column, scope.presence, link_options, true)
|
|
514
|
-
end
|
|
515
|
-
link_options[:class] = 'refresh-link'
|
|
516
|
-
if ui_options[:refresh_link].is_a?(Hash)
|
|
517
|
-
text = ui_options.dig(:refresh_link, :text)
|
|
518
|
-
text = as_(text) if text.is_a?(Symbol)
|
|
519
|
-
link_options.merge! ui_options[:refresh_link].except(:text)
|
|
520
|
-
end
|
|
521
|
-
link_to(text || as_(:refresh), link_options.delete('data-update_url') || html_options['data-update_url'], link_options.except(:object))
|
|
522
|
-
end
|
|
523
|
-
|
|
524
|
-
def active_scaffold_plural_association_options(column, record = nil)
|
|
525
|
-
associated_options = record.send(column.association.name)
|
|
526
|
-
helper_method = association_helper_method(column.association, :sorted_association_options_find)
|
|
527
|
-
[associated_options, associated_options | send(helper_method, column.association, nil, record)]
|
|
528
|
-
end
|
|
529
|
-
|
|
530
|
-
def active_scaffold_input_plural_association(column, options, ui_options: column.options)
|
|
531
|
-
record = options.delete(:object)
|
|
532
|
-
associated_options, select_options = active_scaffold_plural_association_options(column, record)
|
|
533
|
-
|
|
534
|
-
html =
|
|
535
|
-
if options[:multiple] || ui_options.dig(:html_options, :multiple)
|
|
536
|
-
html_options = options.merge(ui_options[:html_options] || {})
|
|
537
|
-
active_scaffold_select_name_with_multiple html_options
|
|
538
|
-
collection_select(:record, column.name, select_options, :id, ui_options[:label_method] || :to_label, ui_options.merge(object: record), html_options)
|
|
539
|
-
elsif select_options.empty?
|
|
540
|
-
content_tag(:span, as_(:no_options), class: "#{options[:class]} no-options", id: options[:id]) <<
|
|
541
|
-
hidden_field_tag("#{options[:name]}[]", '', id: nil)
|
|
542
|
-
else
|
|
543
|
-
active_scaffold_checkbox_list(column, select_options, associated_options.collect(&:id), options, ui_options: ui_options)
|
|
544
|
-
end
|
|
545
|
-
html << active_scaffold_refresh_link(column, options, record, ui_options) if ui_options[:refresh_link]
|
|
546
|
-
html
|
|
547
|
-
end
|
|
548
|
-
|
|
549
|
-
def active_scaffold_input_draggable(column, options, ui_options: column.options)
|
|
550
|
-
active_scaffold_input_select(column, options.merge(draggable_lists: true), ui_options: ui_options)
|
|
551
|
-
end
|
|
552
|
-
|
|
553
|
-
def active_scaffold_checkbox_option(option, label_method, associated_ids, checkbox_options, li_options = {})
|
|
554
|
-
content_tag(:li, li_options) do
|
|
555
|
-
option_id = option.is_a?(Array) ? option[1] : option.id
|
|
556
|
-
label = option.is_a?(Array) ? option[0] : option.send(label_method)
|
|
557
|
-
check_box_tag(checkbox_options[:name], option_id, associated_ids.include?(option_id), checkbox_options) <<
|
|
558
|
-
content_tag(:label, label, for: checkbox_options[:id])
|
|
559
|
-
end
|
|
560
|
-
end
|
|
561
|
-
|
|
562
|
-
def active_scaffold_check_all_buttons(column, options, ui_options: column.options)
|
|
563
|
-
content_tag(:div, class: 'check-buttons') do
|
|
564
|
-
link_to(as_(:check_all), '#', class: 'check-all') <<
|
|
565
|
-
link_to(as_(:uncheck_all), '#', class: 'uncheck-all')
|
|
566
|
-
end
|
|
567
|
-
end
|
|
568
|
-
|
|
569
|
-
def active_scaffold_checkbox_list(column, select_options, associated_ids, options, ui_options: column.options)
|
|
570
|
-
label_method = ui_options[:label_method] || :to_label
|
|
571
|
-
html = active_scaffold_check_all_buttons(column, options, ui_options: ui_options)
|
|
572
|
-
html << hidden_field_tag("#{options[:name]}[]", '', id: nil)
|
|
573
|
-
draggable = options.delete(:draggable_lists) || ui_options[:draggable_lists]
|
|
574
|
-
html << content_tag(:ul, options.merge(class: "#{options[:class]} checkbox-list#{' draggable-lists' if draggable}")) do
|
|
575
|
-
content = []
|
|
576
|
-
select_options.each_with_index do |option, i|
|
|
577
|
-
content << active_scaffold_checkbox_option(option, label_method, associated_ids, name: "#{options[:name]}[]", id: "#{options[:id]}_#{i}_id")
|
|
578
|
-
end
|
|
579
|
-
safe_join content
|
|
580
|
-
end
|
|
581
|
-
html
|
|
582
|
-
end
|
|
583
|
-
|
|
584
|
-
def active_scaffold_translated_option(column, text, value = nil)
|
|
585
|
-
value = text if value.nil?
|
|
586
|
-
[(text.is_a?(Symbol) ? column.active_record_class.human_attribute_name(text) : text), value]
|
|
587
|
-
end
|
|
588
|
-
|
|
589
|
-
def active_scaffold_enum_options(column, record = nil, ui_options: column.options)
|
|
590
|
-
ui_options[:options]
|
|
591
|
-
end
|
|
592
|
-
|
|
593
|
-
def active_scaffold_input_enum(column, html_options, options = {}, ui_options: column.options)
|
|
594
|
-
record = html_options.delete(:object)
|
|
595
|
-
options[:selected] = record.send(column.name)
|
|
596
|
-
options[:object] = record
|
|
597
|
-
enum_options_method = override_helper_per_model(:active_scaffold_enum_options, record.class)
|
|
598
|
-
options_for_select = send(enum_options_method, column, record, ui_options: ui_options).collect do |text, value|
|
|
599
|
-
active_scaffold_translated_option(column, text, value)
|
|
600
|
-
end
|
|
601
|
-
html_options.merge!(ui_options[:html_options] || {})
|
|
602
|
-
options.merge!(ui_options)
|
|
603
|
-
active_scaffold_select_name_with_multiple html_options
|
|
604
|
-
active_scaffold_translate_select_options(options)
|
|
605
|
-
html = select(:record, column.name, options_for_select, options, html_options)
|
|
606
|
-
html << active_scaffold_refresh_link(column, html_options, record, ui_options) if ui_options[:refresh_link]
|
|
607
|
-
html
|
|
608
|
-
end
|
|
609
|
-
|
|
610
|
-
def active_scaffold_input_select(column, html_options, ui_options: column.options)
|
|
611
|
-
record = html_options[:object]
|
|
612
|
-
html =
|
|
613
|
-
if column.association&.singular?
|
|
614
|
-
active_scaffold_input_singular_association(column, html_options, ui_options: ui_options)
|
|
615
|
-
elsif column.association&.collection?
|
|
616
|
-
active_scaffold_input_plural_association(column, html_options, ui_options: ui_options)
|
|
617
|
-
else
|
|
618
|
-
active_scaffold_input_enum(column, html_options, ui_options: ui_options)
|
|
619
|
-
end
|
|
620
|
-
if ui_options[:add_new]
|
|
621
|
-
html = content_tag(:div, html, class: 'select-field') <<
|
|
622
|
-
active_scaffold_add_new(column, record, html_options, ui_options: ui_options)
|
|
623
|
-
end
|
|
624
|
-
html
|
|
625
|
-
end
|
|
626
|
-
|
|
627
|
-
def active_scaffold_input_select_multiple(column, options, ui_options: column.options)
|
|
628
|
-
active_scaffold_input_select(column, options.merge(multiple: true), ui_options: ui_options)
|
|
629
|
-
end
|
|
630
|
-
|
|
631
|
-
def active_scaffold_radio_option(option, selected, column, radio_options, ui_options: column.options)
|
|
632
|
-
if column.association
|
|
633
|
-
label_method = ui_options[:label_method] || :to_label
|
|
634
|
-
text = option.send(label_method)
|
|
635
|
-
value = option.id
|
|
636
|
-
checked = {checked: selected == value}
|
|
637
|
-
else
|
|
638
|
-
text, value = active_scaffold_translated_option(column, *option)
|
|
639
|
-
end
|
|
640
|
-
|
|
641
|
-
id_key = radio_options[:'data-id'] ? :'data-id' : :id
|
|
642
|
-
radio_options = radio_options.merge(id_key => "#{radio_options[id_key]}-#{value.to_s.parameterize}")
|
|
643
|
-
radio_options.merge!(checked) if checked
|
|
644
|
-
content_tag(:label, radio_button(:record, column.name, value, radio_options) + text)
|
|
645
|
-
end
|
|
646
|
-
|
|
647
|
-
def active_scaffold_input_radio_content(column, record, options, html_options, ui_options)
|
|
648
|
-
if ui_options[:add_new]
|
|
649
|
-
add_new_subform = ui_options[:add_new] == true || ui_options[:add_new][:mode].in?([nil, :subform])
|
|
650
|
-
if add_new_subform
|
|
651
|
-
html_options[:data] ||= {}
|
|
652
|
-
html_options[:data][:subform_id] = active_scaffold_subform_attributes(column, ui_options: ui_options)[:id]
|
|
653
|
-
end
|
|
654
|
-
radio_html_options = html_options.merge(class: "#{html_options[:class]} hide-new-subform")
|
|
655
|
-
else
|
|
656
|
-
radio_html_options = html_options
|
|
657
|
-
end
|
|
658
|
-
|
|
659
|
-
selected = record.send(column.association.name) if column.association
|
|
660
|
-
radios = options.map do |option|
|
|
661
|
-
active_scaffold_radio_option(option, selected&.id, column, radio_html_options, ui_options: ui_options)
|
|
662
|
-
end
|
|
663
|
-
|
|
664
|
-
if ui_options[:include_blank]
|
|
665
|
-
label = ui_options[:include_blank]
|
|
666
|
-
label = as_(ui_options[:include_blank]) if ui_options[:include_blank].is_a?(Symbol)
|
|
667
|
-
radio_id = "#{html_options[:id]}-"
|
|
668
|
-
radios.prepend content_tag(:label, radio_button(:record, column.name, '', html_options.merge(id: radio_id)) + label)
|
|
669
|
-
end
|
|
670
|
-
if ui_options[:add_new]
|
|
671
|
-
if add_new_subform
|
|
672
|
-
create_new = content_tag(:label) do
|
|
673
|
-
radio_button_tag(html_options[:name], '', selected&.new_record?, html_options.merge(
|
|
674
|
-
id: "#{html_options[:id]}-create_new", class: "#{html_options[:class]} show-new-subform"
|
|
675
|
-
).except(:object)) <<
|
|
676
|
-
active_scaffold_add_new_text(ui_options[:add_new], :add_new_text, :create_new)
|
|
677
|
-
end
|
|
678
|
-
radios << create_new
|
|
679
|
-
skip_link = true
|
|
680
|
-
else
|
|
681
|
-
ui_options = ui_options.merge(add_new: ui_options[:add_new].merge(
|
|
682
|
-
url_options: {
|
|
683
|
-
parent_scope: html_options[:name].gsub(/^record|\[[^\]]*\]$/, '').presence,
|
|
684
|
-
radio_data: html_options.slice(*html_options.keys.grep(/^data-update_/))
|
|
685
|
-
}
|
|
686
|
-
))
|
|
687
|
-
radios << content_tag(:span, '', class: 'new-radio-container', id: html_options[:id])
|
|
688
|
-
end
|
|
689
|
-
radios << active_scaffold_add_new(column, record, html_options, ui_options: ui_options, skip_link: skip_link)
|
|
690
|
-
end
|
|
691
|
-
|
|
692
|
-
safe_join radios
|
|
693
|
-
end
|
|
694
|
-
|
|
695
|
-
def active_scaffold_input_radio(column, html_options, ui_options: column.options)
|
|
696
|
-
record = html_options[:object]
|
|
697
|
-
html_options.merge!(ui_options[:html_options] || {})
|
|
698
|
-
options =
|
|
699
|
-
if column.association
|
|
700
|
-
helper_method = association_helper_method(column.association, :sorted_association_options_find)
|
|
701
|
-
send(helper_method, column.association, nil, record)
|
|
702
|
-
else
|
|
703
|
-
enum_options_method = override_helper_per_model(:active_scaffold_enum_options, record.class)
|
|
704
|
-
send(enum_options_method, column, record, ui_options: ui_options)
|
|
705
|
-
end
|
|
706
|
-
|
|
707
|
-
if options.present?
|
|
708
|
-
html = active_scaffold_input_radio_content(column, record, options, html_options, ui_options)
|
|
709
|
-
else
|
|
710
|
-
html = content_tag(:span, as_(:no_options), class: "#{html_options[:class]} no-options")
|
|
711
|
-
html << hidden_field_tag(html_options[:name], '', id: html_options[:id])
|
|
712
|
-
if ui_options[:add_new]
|
|
713
|
-
html = content_tag(:div, html, class: 'select-field') <<
|
|
714
|
-
active_scaffold_add_new(column, record, html_options, ui_options: ui_options)
|
|
715
|
-
end
|
|
716
|
-
html
|
|
717
|
-
end
|
|
718
|
-
html << active_scaffold_refresh_link(column, html_options, record, ui_options.merge(field_selector: "[name=\"#{html_options[:name]}\"]")) if ui_options[:refresh_link]
|
|
719
|
-
html
|
|
720
|
-
end
|
|
721
|
-
|
|
722
|
-
def active_scaffold_input_checkbox(column, options, ui_options: column.options)
|
|
723
|
-
check_box(:record, column.name, options.merge(ui_options))
|
|
724
|
-
end
|
|
725
|
-
|
|
726
|
-
def active_scaffold_input_password(column, options, ui_options: column.options)
|
|
727
|
-
active_scaffold_text_input :password_field, column, options.reverse_merge(autocomplete: 'new-password'), ui_options: ui_options
|
|
728
|
-
end
|
|
729
|
-
|
|
730
|
-
def active_scaffold_input_textarea(column, options, ui_options: column.options)
|
|
731
|
-
text_area(:record, column.name, options.merge(cols: ui_options[:cols], rows: ui_options[:rows], size: ui_options[:size]))
|
|
732
|
-
end
|
|
733
|
-
|
|
734
|
-
def active_scaffold_input_virtual(column, options)
|
|
735
|
-
active_scaffold_text_input :text_field, column, options
|
|
736
|
-
end
|
|
737
|
-
|
|
738
|
-
# Some fields from HTML5 (primarily for using in-browser validation)
|
|
739
|
-
# Sadly, many of them lacks browser support
|
|
740
|
-
|
|
741
|
-
# A text box, that accepts only valid email address (in-browser validation)
|
|
742
|
-
def active_scaffold_input_email(column, options, ui_options: column.options)
|
|
743
|
-
active_scaffold_text_input :email_field, column, options, ui_options: ui_options
|
|
744
|
-
end
|
|
745
|
-
|
|
746
|
-
# A text box, that accepts only valid URI (in-browser validation)
|
|
747
|
-
def active_scaffold_input_url(column, options, ui_options: column.options)
|
|
748
|
-
active_scaffold_text_input :url_field, column, options, ui_options: ui_options
|
|
749
|
-
end
|
|
750
|
-
|
|
751
|
-
# A text box, that accepts only valid phone-number (in-browser validation)
|
|
752
|
-
def active_scaffold_input_telephone(column, options, ui_options: column.options)
|
|
753
|
-
active_scaffold_text_input :telephone_field, column, options, :format, ui_options: ui_options
|
|
754
|
-
end
|
|
755
|
-
|
|
756
|
-
# A spinbox control for number values (in-browser validation)
|
|
757
|
-
def active_scaffold_input_number(column, options, ui_options: column.options)
|
|
758
|
-
active_scaffold_number_input :number_field, column, options, :format, ui_options: ui_options
|
|
759
|
-
end
|
|
760
|
-
|
|
761
|
-
# A slider control for number values (in-browser validation)
|
|
762
|
-
def active_scaffold_input_range(column, options, ui_options: column.options)
|
|
763
|
-
active_scaffold_number_input :range_field, column, options, :format, ui_options: ui_options
|
|
764
|
-
end
|
|
765
|
-
|
|
766
|
-
# A slider control for number values (in-browser validation)
|
|
767
|
-
def active_scaffold_number_input(method, column, options, remove_options = nil, ui_options: column.options)
|
|
768
|
-
options = numerical_constraints_for_column(column, options)
|
|
769
|
-
active_scaffold_text_input method, column, options, remove_options, ui_options: ui_options
|
|
770
|
-
end
|
|
771
|
-
|
|
772
|
-
def active_scaffold_text_input(method, column, options, remove_options = nil, ui_options: column.options)
|
|
773
|
-
options = active_scaffold_input_text_options(options)
|
|
774
|
-
options = options.merge(ui_options)
|
|
775
|
-
options = options.except(*remove_options) if remove_options.present?
|
|
776
|
-
send method, :record, column.name, options
|
|
777
|
-
end
|
|
778
|
-
|
|
779
|
-
# A color picker
|
|
780
|
-
def active_scaffold_input_color(column, options, ui_options: column.options)
|
|
781
|
-
html = []
|
|
782
|
-
options = active_scaffold_input_text_options(options)
|
|
783
|
-
if column.null?
|
|
784
|
-
no_color = options[:object].send(column.name).nil?
|
|
785
|
-
method = no_color ? :hidden_field : :color_field
|
|
786
|
-
html << content_tag(:label, check_box_tag('disable', '1', no_color, id: nil, name: nil, class: 'no-color') << " #{as_ ui_options[:no_color] || :no_color}")
|
|
787
|
-
else
|
|
788
|
-
method = :color_field
|
|
789
|
-
end
|
|
790
|
-
html << send(method, :record, column.name, options.merge(ui_options).except(:format, :no_color))
|
|
791
|
-
safe_join html
|
|
792
|
-
end
|
|
793
|
-
|
|
794
|
-
#
|
|
795
|
-
# Column.type-based inputs
|
|
796
|
-
#
|
|
797
|
-
|
|
798
|
-
def active_scaffold_input_boolean(column, html_options, ui_options: column.options)
|
|
799
|
-
record = html_options.delete(:object)
|
|
800
|
-
html_options.merge!(ui_options[:html_options] || {})
|
|
801
|
-
|
|
802
|
-
options = {selected: record.send(column.name), object: record}
|
|
803
|
-
options[:include_blank] = :_select_ if column.null?
|
|
804
|
-
options.merge!(ui_options)
|
|
805
|
-
active_scaffold_translate_select_options(options)
|
|
806
|
-
|
|
807
|
-
options_for_select = [[as_(:true), true], [as_(:false), false]] # rubocop:disable Lint/BooleanSymbol
|
|
808
|
-
select(:record, column.name, options_for_select, options, html_options)
|
|
809
|
-
end
|
|
810
|
-
|
|
811
|
-
def active_scaffold_input_date(column, options, ui_options: column.options)
|
|
812
|
-
active_scaffold_text_input :date_field, column, options, ui_options: ui_options
|
|
813
|
-
end
|
|
814
|
-
|
|
815
|
-
def active_scaffold_input_time(column, options, ui_options: column.options)
|
|
816
|
-
active_scaffold_text_input :time_field, column, options, ui_options: ui_options
|
|
817
|
-
end
|
|
818
|
-
|
|
819
|
-
def active_scaffold_input_datetime(column, options, ui_options: column.options)
|
|
820
|
-
active_scaffold_text_input :datetime_local_field, column, options, ui_options: ui_options
|
|
821
|
-
end
|
|
822
|
-
|
|
823
|
-
def active_scaffold_input_month(column, options, ui_options: column.options)
|
|
824
|
-
active_scaffold_text_input :month_field, column, options, ui_options: ui_options
|
|
825
|
-
end
|
|
826
|
-
|
|
827
|
-
def active_scaffold_input_week(column, options, ui_options: column.options)
|
|
828
|
-
active_scaffold_text_input :week_field, column, options, ui_options: ui_options
|
|
829
|
-
end
|
|
830
|
-
|
|
831
356
|
##
|
|
832
357
|
## Form column override signatures
|
|
833
358
|
##
|