active_scaffold 3.7.0 → 3.7.1

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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.rdoc +20 -0
  3. data/README.md +2 -0
  4. data/app/assets/javascripts/jquery/active_scaffold.js +68 -62
  5. data/app/assets/stylesheets/active_scaffold_layout.css +1 -1
  6. data/app/views/active_scaffold_overrides/_form_association_record.html.erb +2 -1
  7. data/app/views/active_scaffold_overrides/_render_field.js.erb +9 -6
  8. data/config/locales/de.yml +6 -3
  9. data/config/locales/en.yml +3 -0
  10. data/config/locales/es.yml +3 -0
  11. data/config/locales/fr.yml +9 -6
  12. data/config/locales/hu.yml +20 -17
  13. data/config/locales/ja.yml +25 -22
  14. data/config/locales/ru.yml +17 -14
  15. data/lib/active_scaffold/actions/update.rb +3 -3
  16. data/lib/active_scaffold/attribute_params.rb +7 -17
  17. data/lib/active_scaffold/bridges/active_storage/form_ui.rb +6 -6
  18. data/lib/active_scaffold/bridges/active_storage/list_ui.rb +7 -7
  19. data/lib/active_scaffold/bridges/ancestry/ancestry_bridge.rb +2 -2
  20. data/lib/active_scaffold/bridges/calendar_date_select/as_cds_bridge.rb +12 -14
  21. data/lib/active_scaffold/bridges/carrierwave/form_ui.rb +2 -2
  22. data/lib/active_scaffold/bridges/carrierwave/list_ui.rb +1 -1
  23. data/lib/active_scaffold/bridges/chosen/helpers.rb +10 -10
  24. data/lib/active_scaffold/bridges/country_select/country_select_bridge_helper.rb +7 -7
  25. data/lib/active_scaffold/bridges/date_picker/ext.rb +20 -9
  26. data/lib/active_scaffold/bridges/date_picker/helper.rb +5 -5
  27. data/lib/active_scaffold/bridges/date_picker.rb +2 -0
  28. data/lib/active_scaffold/bridges/dragonfly/form_ui.rb +3 -3
  29. data/lib/active_scaffold/bridges/dragonfly/list_ui.rb +5 -5
  30. data/lib/active_scaffold/bridges/file_column/form_ui.rb +1 -1
  31. data/lib/active_scaffold/bridges/file_column/list_ui.rb +3 -3
  32. data/lib/active_scaffold/bridges/file_column/test/functional/file_column_keep_test.rb +1 -1
  33. data/lib/active_scaffold/bridges/paperclip/form_ui.rb +3 -3
  34. data/lib/active_scaffold/bridges/paperclip/list_ui.rb +1 -1
  35. data/lib/active_scaffold/bridges/record_select/helpers.rb +15 -15
  36. data/lib/active_scaffold/bridges/tiny_mce/helpers.rb +6 -6
  37. data/lib/active_scaffold/bridges/usa_state_select/usa_state_select_helper.rb +5 -5
  38. data/lib/active_scaffold/bridges.rb +0 -3
  39. data/lib/active_scaffold/constraints.rb +22 -7
  40. data/lib/active_scaffold/core.rb +5 -3
  41. data/lib/active_scaffold/data_structures/column.rb +108 -23
  42. data/lib/active_scaffold/engine.rb +15 -0
  43. data/lib/active_scaffold/extensions/routing_mapper.rb +1 -0
  44. data/lib/active_scaffold/finder.rb +142 -27
  45. data/lib/active_scaffold/helpers/controller_helpers.rb +9 -4
  46. data/lib/active_scaffold/helpers/form_column_helpers.rb +114 -94
  47. data/lib/active_scaffold/helpers/human_condition_helpers.rb +48 -14
  48. data/lib/active_scaffold/helpers/list_column_helpers.rb +34 -18
  49. data/lib/active_scaffold/helpers/search_column_helpers.rb +131 -55
  50. data/lib/active_scaffold/helpers/show_column_helpers.rb +6 -6
  51. data/lib/active_scaffold/orm_checks.rb +21 -1
  52. data/lib/active_scaffold/version.rb +1 -1
  53. data/lib/active_scaffold.rb +3 -2
  54. data/test/bridges/date_picker_test.rb +3 -2
  55. data/test/bridges/paperclip_test.rb +3 -2
  56. data/test/bridges/tiny_mce_test.rb +4 -2
  57. data/test/helpers/form_column_helpers_test.rb +7 -5
  58. data/test/helpers/search_column_helpers_test.rb +2 -1
  59. data/test/misc/constraints_test.rb +1 -0
  60. data/test/misc/finder_test.rb +38 -0
  61. metadata +2 -6
  62. data/config/brakeman.ignore +0 -26
  63. data/config/brakeman.yml +0 -3
  64. data/config/i18n-tasks.yml +0 -121
  65. data/lib/active_scaffold/bridges/shared/date_bridge.rb +0 -221
@@ -19,7 +19,7 @@ module ActiveScaffold
19
19
 
20
20
  # second, check if the dev has specified a valid form_ui for this column
21
21
  elsif column.form_ui && (method = override_input(column.form_ui))
22
- send(method, column, options)
22
+ send(method, column, options, ui_options: (column.form_ui_options || column.options).except(:collapsible))
23
23
 
24
24
  elsif column.association
25
25
  # if we get here, it's because the column has a form_ui but not one ActiveScaffold knows about.
@@ -32,15 +32,15 @@ module ActiveScaffold
32
32
  options[:value] = format_number_value(record.send(column.name), column.options) if column.number?
33
33
  active_scaffold_input_virtual(column, options)
34
34
 
35
- elsif (method = override_input(column.column.type)) # regular model attribute column
35
+ elsif (method = override_input(column.column_type)) # regular model attribute column
36
36
  # if we (or someone else) have created a custom render option for the column type, use that
37
37
  send(method, column, options)
38
38
 
39
39
  else # final ultimate fallback: use rails' generic input method
40
40
  # for textual fields we pass different options
41
41
  options = active_scaffold_input_text_options(options) if column.text? || column.number?
42
- if column.column.type == :string && options[:maxlength].blank?
43
- options[:maxlength] = column.column.limit
42
+ if column.column_type == :string && options[:maxlength].blank?
43
+ options[:maxlength] = column.type_for_attribute.limit
44
44
  options[:size] ||= options[:maxlength].to_i > 30 ? 30 : options[:maxlength]
45
45
  end
46
46
  options[:value] = format_number_value(record.send(column.name), column.options) if column.number?
@@ -106,7 +106,7 @@ module ActiveScaffold
106
106
  classes = "#{column.name}-input"
107
107
  classes += ' numeric-input' if column.number?
108
108
 
109
- if column.options[:collapsible]
109
+ if (column.form_ui_options || column.options)[:collapsible]
110
110
  collapsible_id = "container_#{id_control}"
111
111
  end
112
112
 
@@ -129,7 +129,7 @@ module ActiveScaffold
129
129
  if @main_columns && (scope.nil? || subform_controller == controller.class)
130
130
  form_columns ||= @main_columns.visible_columns_names
131
131
  end
132
- form_columns ||= options[:form_columns] || current_form_columns(record, scope, subform_controller)
132
+ form_columns ||= current_form_columns(record, scope, subform_controller)
133
133
  if force || (form_columns && column.update_columns && (column.update_columns & form_columns).present?)
134
134
  url_params.reverse_merge! params_for(action: 'render_field', column: column.name, id: record.to_param)
135
135
  if nested? && scope
@@ -186,6 +186,7 @@ module ActiveScaffold
186
186
 
187
187
  def form_attribute(column, record, scope = nil, only_value = false, col_class = nil)
188
188
  column_options = active_scaffold_input_options(column, scope, :object => record)
189
+ collapsible_id = column_options.delete :collapsible_id
189
190
  attributes = field_attributes(column, record)
190
191
  attributes[:class] = "#{attributes[:class]} #{col_class}" if col_class.present?
191
192
  if only_value
@@ -206,7 +207,6 @@ module ActiveScaffold
206
207
  end
207
208
 
208
209
  label = label_tag(label_for(column, column_options), form_column_label(column, record, scope))
209
- collapsible_id = column_options.delete :collapsible_id
210
210
  label << h(' ') << link_to_visibility_toggle(collapsible_id) if collapsible_id
211
211
  content_tag :dl, attributes do
212
212
  content_tag(:dt, label) << content_tag(:dd, field, id: collapsible_id)
@@ -309,7 +309,7 @@ module ActiveScaffold
309
309
  options[:name] = "#{options[:name]}[]"
310
310
  end
311
311
 
312
- def active_scaffold_input_singular_association(column, html_options, options = {})
312
+ def active_scaffold_input_singular_association(column, html_options, options = {}, ui_options: column.options)
313
313
  record = html_options.delete(:object)
314
314
  associated = record.send(column.association.name)
315
315
 
@@ -319,8 +319,8 @@ module ActiveScaffold
319
319
  method = column.name
320
320
  options.merge! :selected => associated&.id, :include_blank => as_(:_select_), :object => record
321
321
 
322
- html_options.merge!(column.options[:html_options] || {})
323
- options.merge!(column.options)
322
+ html_options.merge!(ui_options[:html_options] || {})
323
+ options.merge!(ui_options)
324
324
  html_options.delete(:multiple) # no point using multiple in a form for singular assoc, but may be set for field search
325
325
  active_scaffold_translate_select_options(options)
326
326
 
@@ -328,18 +328,18 @@ module ActiveScaffold
328
328
  if (optgroup = options.delete(:optgroup))
329
329
  select(:record, method, active_scaffold_grouped_options(column, select_options, optgroup), options, html_options)
330
330
  else
331
- collection_select(:record, method, select_options, :id, column.options[:label_method] || :to_label, options, html_options)
331
+ collection_select(:record, method, select_options, :id, ui_options[:label_method] || :to_label, options, html_options)
332
332
  end
333
- html << active_scaffold_refresh_link(column, html_options, record) if column.options[:refresh_link]
334
- html << active_scaffold_new_record_subform(column, record, html_options) if column.options[:add_new]
333
+ html << active_scaffold_refresh_link(column, html_options, record, ui_options) if ui_options[:refresh_link]
334
+ html << active_scaffold_new_record_subform(column, record, html_options, ui_options: ui_options) if ui_options[:add_new]
335
335
  html
336
336
  end
337
337
 
338
- def active_scaffold_new_record_subform(column, record, html_options, new_record_attributes: nil, locals: {}, skip_link: false)
338
+ def active_scaffold_new_record_subform(column, record, html_options, ui_options: column.options, new_record_attributes: nil, locals: {}, skip_link: false)
339
339
  klass =
340
340
  if column.association.polymorphic? && column.association.belongs_to?
341
341
  type = record.send(column.association.foreign_type)
342
- column.association.klass(record) if type.present? && (column.options[:add_new] == true || type.in?(column.options[:add_new]))
342
+ column.association.klass(record) if type.present? && (ui_options[:add_new] == true || type.in?(ui_options[:add_new]))
343
343
  else
344
344
  column.association.klass
345
345
  end
@@ -354,8 +354,8 @@ module ActiveScaffold
354
354
  scope = html_options[:name].scan(/record(.*)\[#{column.name}\]/).dig(0, 0)
355
355
  new_record ||= klass.new(new_record_attributes)
356
356
  locals = locals.reverse_merge(column: column, parent_record: record, associated: [], show_blank_record: new_record, scope: scope)
357
- subform = render(partial: subform_partial_for_column(column, klass), locals: locals)
358
- if column.options[:hide_subgroups]
357
+ subform = render(partial: subform_partial_for_column(column, klass, ui_options: ui_options), locals: locals)
358
+ if ui_options[:hide_subgroups]
359
359
  toggable_id = "#{sub_form_id(association: column.name, id: record.id || generated_id(record) || 99_999_999_999)}-div"
360
360
  subform << link_to_visibility_toggle(toggable_id, default_visible: false)
361
361
  end
@@ -370,8 +370,8 @@ module ActiveScaffold
370
370
  link_to(label, '#', data: data, class: 'show-new-subform')
371
371
  end
372
372
 
373
- def active_scaffold_file_with_remove_link(column, options, content, remove_file_prefix, controls_class, &block) # rubocop:disable Metrics/ParameterLists
374
- options = active_scaffold_input_text_options(options.merge(column.options))
373
+ def active_scaffold_file_with_remove_link(column, options, content, remove_file_prefix, controls_class, ui_options: column.options, &block) # rubocop:disable Metrics/ParameterLists
374
+ options = active_scaffold_input_text_options(options.merge(ui_options))
375
375
  if content
376
376
  active_scaffold_file_with_content(column, content, options, remove_file_prefix, controls_class, &block)
377
377
  else
@@ -404,7 +404,7 @@ module ActiveScaffold
404
404
  end
405
405
  end
406
406
 
407
- def active_scaffold_refresh_link(column, html_options, record)
407
+ def active_scaffold_refresh_link(column, html_options, record, ui_options = {})
408
408
  link_options = {:object => record}
409
409
  if html_options['data-update_url']
410
410
  link_options['data-update_send_form'] = html_options['data-update_send_form']
@@ -414,7 +414,12 @@ module ActiveScaffold
414
414
  link_options = update_columns_options(column, scope.presence, link_options, true)
415
415
  end
416
416
  link_options[:class] = 'refresh-link'
417
- link_to(as_(:refresh), link_options.delete('data-update_url') || html_options['data-update_url'], link_options)
417
+ if ui_options[:refresh_link].is_a?(Hash)
418
+ text = ui_options.dig(:refresh_link, :text)
419
+ text = as_(text) if text.is_a?(Symbol)
420
+ link_options.merge! ui_options[:refresh_link].except(:text)
421
+ end
422
+ link_to(text || as_(:refresh), link_options.delete('data-update_url') || html_options['data-update_url'], link_options.except(:object))
418
423
  end
419
424
 
420
425
  def active_scaffold_plural_association_options(column, record = nil)
@@ -422,21 +427,29 @@ module ActiveScaffold
422
427
  [associated_options, associated_options | sorted_association_options_find(column.association, nil, record)]
423
428
  end
424
429
 
425
- def active_scaffold_input_plural_association(column, options)
430
+ def active_scaffold_input_plural_association(column, options, ui_options: column.options)
426
431
  record = options.delete(:object)
427
432
  associated_options, select_options = active_scaffold_plural_association_options(column, record)
428
433
 
429
434
  html =
430
- if select_options.empty?
435
+ if options[:multiple] || ui_options.dig(:html_options, :multiple)
436
+ html_options = options.merge(ui_options[:html_options] || {})
437
+ active_scaffold_select_name_with_multiple html_options
438
+ collection_select(:record, column.name, select_options, :id, ui_options[:label_method] || :to_label, ui_options.merge(object: record), html_options)
439
+ elsif select_options.empty?
431
440
  content_tag(:span, as_(:no_options), :class => "#{options[:class]} no-options", :id => options[:id]) <<
432
441
  hidden_field_tag("#{options[:name]}[]", '', :id => nil)
433
442
  else
434
- active_scaffold_checkbox_list(column, select_options, associated_options.collect(&:id), options)
443
+ active_scaffold_checkbox_list(column, select_options, associated_options.collect(&:id), options, ui_options: ui_options)
435
444
  end
436
- html << active_scaffold_refresh_link(column, options, record) if column.options[:refresh_link]
445
+ html << active_scaffold_refresh_link(column, options, record, ui_options) if ui_options[:refresh_link]
437
446
  html
438
447
  end
439
448
 
449
+ def active_scaffold_input_draggable(column, options, ui_options: column.options)
450
+ active_scaffold_input_plural_association(column, options.merge(draggable_lists: true), ui_options: ui_options)
451
+ end
452
+
440
453
  def active_scaffold_checkbox_option(option, label_method, associated_ids, checkbox_options, li_options = {})
441
454
  content_tag(:li, li_options) do
442
455
  option_id = option.is_a?(Array) ? option[1] : option.id
@@ -446,10 +459,11 @@ module ActiveScaffold
446
459
  end
447
460
  end
448
461
 
449
- def active_scaffold_checkbox_list(column, select_options, associated_ids, options)
450
- label_method = column.options[:label_method] || :to_label
462
+ def active_scaffold_checkbox_list(column, select_options, associated_ids, options, ui_options: column.options)
463
+ label_method = ui_options[:label_method] || :to_label
451
464
  html = hidden_field_tag("#{options[:name]}[]", '', :id => nil)
452
- html << content_tag(:ul, options.merge(:class => "#{options[:class]} checkbox-list#{' draggable-lists' if column.options[:draggable_lists]}")) do
465
+ draggable = options.delete(:draggable_lists) || ui_options[:draggable_lists]
466
+ html << content_tag(:ul, options.merge(:class => "#{options[:class]} checkbox-list#{' draggable-lists' if draggable}")) do
453
467
  content = []
454
468
  select_options.each_with_index do |option, i|
455
469
  content << active_scaffold_checkbox_option(option, label_method, associated_ids, :name => "#{options[:name]}[]", :id => "#{options[:id]}_#{i}_id")
@@ -464,37 +478,43 @@ module ActiveScaffold
464
478
  [(text.is_a?(Symbol) ? column.active_record_class.human_attribute_name(text) : text), value]
465
479
  end
466
480
 
467
- def active_scaffold_enum_options(column, record = nil)
468
- column.options[:options]
481
+ def active_scaffold_enum_options(column, record = nil, ui_options: column.options)
482
+ ui_options[:options]
469
483
  end
470
484
 
471
- def active_scaffold_input_enum(column, html_options, options = {})
485
+ def active_scaffold_input_enum(column, html_options, options = {}, ui_options: column.options)
472
486
  record = html_options.delete(:object)
473
487
  options[:selected] = record.send(column.name)
474
488
  options[:object] = record
475
- options_for_select = active_scaffold_enum_options(column, record).collect do |text, value|
489
+ options_for_select = active_scaffold_enum_options(column, record, ui_options: ui_options).collect do |text, value|
476
490
  active_scaffold_translated_option(column, text, value)
477
491
  end
478
- html_options.merge!(column.options[:html_options] || {})
479
- options.merge!(column.options)
492
+ html_options.merge!(ui_options[:html_options] || {})
493
+ options.merge!(ui_options)
480
494
  active_scaffold_select_name_with_multiple html_options
481
495
  active_scaffold_translate_select_options(options)
482
- select(:record, column.name, options_for_select, options, html_options)
496
+ html = select(:record, column.name, options_for_select, options, html_options)
497
+ html << active_scaffold_refresh_link(column, html_options, record, ui_options) if ui_options[:refresh_link]
498
+ html
483
499
  end
484
500
 
485
- def active_scaffold_input_select(column, html_options)
501
+ def active_scaffold_input_select(column, html_options, ui_options: column.options)
486
502
  if column.association&.singular?
487
- active_scaffold_input_singular_association(column, html_options)
503
+ active_scaffold_input_singular_association(column, html_options, ui_options: ui_options)
488
504
  elsif column.association&.collection?
489
- active_scaffold_input_plural_association(column, html_options)
505
+ active_scaffold_input_plural_association(column, html_options, ui_options: ui_options)
490
506
  else
491
- active_scaffold_input_enum(column, html_options)
507
+ active_scaffold_input_enum(column, html_options, ui_options: ui_options)
492
508
  end
493
509
  end
494
510
 
495
- def active_scaffold_radio_option(option, selected, column, radio_options)
511
+ def active_scaffold_input_select_multiple(column, options, ui_options: column.options)
512
+ active_scaffold_input_select(column, options.merge(multiple: true), ui_options: ui_options)
513
+ end
514
+
515
+ def active_scaffold_radio_option(option, selected, column, radio_options, ui_options: column.options)
496
516
  if column.association
497
- label_method = column.options[:label_method] || :to_label
517
+ label_method = ui_options[:label_method] || :to_label
498
518
  text = option.send(label_method)
499
519
  value = option.id
500
520
  checked = {:checked => selected == value}
@@ -508,20 +528,20 @@ module ActiveScaffold
508
528
  content_tag(:label, radio_button(:record, column.name, value, radio_options) + text)
509
529
  end
510
530
 
511
- def active_scaffold_input_radio(column, html_options)
531
+ def active_scaffold_input_radio(column, html_options, ui_options: column.options)
512
532
  record = html_options[:object]
513
- html_options.merge!(column.options[:html_options] || {})
533
+ html_options.merge!(ui_options[:html_options] || {})
514
534
  options =
515
535
  if column.association
516
536
  sorted_association_options_find(column.association, nil, record)
517
537
  else
518
- active_scaffold_enum_options(column, record)
538
+ active_scaffold_enum_options(column, record, ui_options: ui_options)
519
539
  end
520
540
 
521
541
  selected = record.send(column.association.name) if column.association
522
542
  selected_id = selected&.id
523
543
  if options.present?
524
- if column.options[:add_new]
544
+ if ui_options[:add_new]
525
545
  html_options[:data] ||= {}
526
546
  html_options[:data][:subform_id] = active_scaffold_subform_attributes(column)[:id]
527
547
  radio_html_options = html_options.merge(class: html_options[:class] + ' hide-new-subform')
@@ -529,37 +549,37 @@ module ActiveScaffold
529
549
  radio_html_options = html_options
530
550
  end
531
551
  radios = options.map do |option|
532
- active_scaffold_radio_option(option, selected_id, column, radio_html_options)
552
+ active_scaffold_radio_option(option, selected_id, column, radio_html_options, ui_options: ui_options)
533
553
  end
534
- if column.options[:include_blank]
535
- label = column.options[:include_blank]
536
- label = as_(column.options[:include_blank]) if column.options[:include_blank].is_a?(Symbol)
554
+ if ui_options[:include_blank]
555
+ label = ui_options[:include_blank]
556
+ label = as_(ui_options[:include_blank]) if ui_options[:include_blank].is_a?(Symbol)
537
557
  radios.prepend content_tag(:label, radio_button(:record, column.name, '', html_options.merge(id: nil)) + label)
538
558
  end
539
- if column.options[:add_new]
540
- create_new_button = radio_button_tag(html_options[:name], '', selected&.new_record?, html_options.merge(id: nil, class: html_options[:class] + ' show-new-subform'))
559
+ if ui_options[:add_new]
560
+ create_new_button = radio_button_tag(html_options[:name], '', selected&.new_record?, html_options.merge(id: nil, class: html_options[:class] + ' show-new-subform').except(:object))
541
561
  radios << content_tag(:label, create_new_button << as_(:create_new)) <<
542
- active_scaffold_new_record_subform(column, record, html_options, skip_link: true)
562
+ active_scaffold_new_record_subform(column, record, html_options, ui_options: ui_options, skip_link: true)
543
563
  end
544
564
  safe_join radios
545
565
  else
546
566
  html = content_tag(:span, as_(:no_options), :class => "#{html_options[:class]} no-options", :id => html_options[:id])
547
567
  html << hidden_field_tag(html_options[:name], '', :id => nil)
548
- html << active_scaffold_new_record_subform(column, record, html_options) if column.options[:add_new]
568
+ html << active_scaffold_new_record_subform(column, record, html_options, ui_options: ui_options) if ui_options[:add_new]
549
569
  html
550
570
  end
551
571
  end
552
572
 
553
- def active_scaffold_input_checkbox(column, options)
554
- check_box(:record, column.name, options.merge(column.options))
573
+ def active_scaffold_input_checkbox(column, options, ui_options: column.options)
574
+ check_box(:record, column.name, options.merge(ui_options))
555
575
  end
556
576
 
557
- def active_scaffold_input_password(column, options)
558
- active_scaffold_text_input :password_field, column, options.reverse_merge(autocomplete: 'new-password')
577
+ def active_scaffold_input_password(column, options, ui_options: column.options)
578
+ active_scaffold_text_input :password_field, column, options.reverse_merge(autocomplete: 'new-password'), ui_options: ui_options
559
579
  end
560
580
 
561
- def active_scaffold_input_textarea(column, options)
562
- text_area(:record, column.name, options.merge(:cols => column.options[:cols], :rows => column.options[:rows], :size => column.options[:size]))
581
+ def active_scaffold_input_textarea(column, options, ui_options: column.options)
582
+ text_area(:record, column.name, options.merge(cols: ui_options[:cols], rows: ui_options[:rows], size: ui_options[:size]))
563
583
  end
564
584
 
565
585
  def active_scaffold_input_virtual(column, options)
@@ -570,55 +590,55 @@ module ActiveScaffold
570
590
  # Sadly, many of them lacks browser support
571
591
 
572
592
  # A text box, that accepts only valid email address (in-browser validation)
573
- def active_scaffold_input_email(column, options)
574
- active_scaffold_text_input :email_field, column, options
593
+ def active_scaffold_input_email(column, options, ui_options: column.options)
594
+ active_scaffold_text_input :email_field, column, options, ui_options: ui_options
575
595
  end
576
596
 
577
597
  # A text box, that accepts only valid URI (in-browser validation)
578
- def active_scaffold_input_url(column, options)
579
- active_scaffold_text_input :url_field, column, options
598
+ def active_scaffold_input_url(column, options, ui_options: column.options)
599
+ active_scaffold_text_input :url_field, column, options, ui_options: ui_options
580
600
  end
581
601
 
582
602
  # A text box, that accepts only valid phone-number (in-browser validation)
583
- def active_scaffold_input_telephone(column, options)
584
- active_scaffold_text_input :telephone_field, column, options, :format
603
+ def active_scaffold_input_telephone(column, options, ui_options: column.options)
604
+ active_scaffold_text_input :telephone_field, column, options, :format, ui_options: ui_options
585
605
  end
586
606
 
587
607
  # A spinbox control for number values (in-browser validation)
588
- def active_scaffold_input_number(column, options)
589
- active_scaffold_number_input :number_field, column, options, :format
608
+ def active_scaffold_input_number(column, options, ui_options: column.options)
609
+ active_scaffold_number_input :number_field, column, options, :format, ui_options: ui_options
590
610
  end
591
611
 
592
612
  # A slider control for number values (in-browser validation)
593
- def active_scaffold_input_range(column, options)
594
- active_scaffold_number_input :range_field, column, options, :format
613
+ def active_scaffold_input_range(column, options, ui_options: column.options)
614
+ active_scaffold_number_input :range_field, column, options, :format, ui_options: ui_options
595
615
  end
596
616
 
597
617
  # A slider control for number values (in-browser validation)
598
- def active_scaffold_number_input(method, column, options, remove_options = nil)
618
+ def active_scaffold_number_input(method, column, options, remove_options = nil, ui_options: column.options)
599
619
  options = numerical_constraints_for_column(column, options)
600
- active_scaffold_text_input method, column, options, remove_options
620
+ active_scaffold_text_input method, column, options, remove_options, ui_options: ui_options
601
621
  end
602
622
 
603
- def active_scaffold_text_input(method, column, options, remove_options = nil)
623
+ def active_scaffold_text_input(method, column, options, remove_options = nil, ui_options: column.options)
604
624
  options = active_scaffold_input_text_options(options)
605
- options = options.merge(column.options)
625
+ options = options.merge(ui_options)
606
626
  options = options.except(*remove_options) if remove_options.present?
607
627
  send method, :record, column.name, options
608
628
  end
609
629
 
610
630
  # A color picker
611
- def active_scaffold_input_color(column, options)
631
+ def active_scaffold_input_color(column, options, ui_options: column.options)
612
632
  html = []
613
633
  options = active_scaffold_input_text_options(options)
614
- if column.column&.null
634
+ if column.null?
615
635
  no_color = options[:object].send(column.name).nil?
616
636
  method = no_color ? :hidden_field : :color_field
617
- html << content_tag(:label, check_box_tag('disable', '1', no_color, id: nil, name: nil, class: 'no-color') << " #{as_ column.options[:no_color] || :no_color}")
637
+ 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}")
618
638
  else
619
639
  method = :color_field
620
640
  end
621
- html << send(method, :record, column.name, options.merge(column.options).except(:format, :no_color))
641
+ html << send(method, :record, column.name, options.merge(ui_options).except(:format, :no_color))
622
642
  safe_join html
623
643
  end
624
644
 
@@ -626,37 +646,37 @@ module ActiveScaffold
626
646
  # Column.type-based inputs
627
647
  #
628
648
 
629
- def active_scaffold_input_boolean(column, html_options)
649
+ def active_scaffold_input_boolean(column, html_options, ui_options: column.options)
630
650
  record = html_options.delete(:object)
631
- html_options.merge!(column.options[:html_options] || {})
651
+ html_options.merge!(ui_options[:html_options] || {})
632
652
 
633
653
  options = {selected: record.send(column.name), object: record}
634
- options[:include_blank] = :_select_ if column.column&.null
635
- options.merge!(column.options)
654
+ options[:include_blank] = :_select_ if column.null?
655
+ options.merge!(ui_options)
636
656
  active_scaffold_translate_select_options(options)
637
657
 
638
658
  options_for_select = [[as_(:true), true], [as_(:false), false]] # rubocop:disable Lint/BooleanSymbol
639
659
  select(:record, column.name, options_for_select, options, html_options)
640
660
  end
641
661
 
642
- def active_scaffold_input_date(column, options)
643
- active_scaffold_text_input :date_field, column, options
662
+ def active_scaffold_input_date(column, options, ui_options: column.options)
663
+ active_scaffold_text_input :date_field, column, options, ui_options: ui_options
644
664
  end
645
665
 
646
- def active_scaffold_input_time(column, options)
647
- active_scaffold_text_input :time_field, column, options
666
+ def active_scaffold_input_time(column, options, ui_options: column.options)
667
+ active_scaffold_text_input :time_field, column, options, ui_options: ui_options
648
668
  end
649
669
 
650
- def active_scaffold_input_datetime(column, options)
651
- active_scaffold_text_input :datetime_local_field, column, options
670
+ def active_scaffold_input_datetime(column, options, ui_options: column.options)
671
+ active_scaffold_text_input :datetime_local_field, column, options, ui_options: ui_options
652
672
  end
653
673
 
654
- def active_scaffold_input_month(column, options)
655
- active_scaffold_text_input :month_field, column, options
674
+ def active_scaffold_input_month(column, options, ui_options: column.options)
675
+ active_scaffold_text_input :month_field, column, options, ui_options: ui_options
656
676
  end
657
677
 
658
- def active_scaffold_input_week(column, options)
659
- active_scaffold_text_input :week_field, column, options
678
+ def active_scaffold_input_week(column, options, ui_options: column.options)
679
+ active_scaffold_text_input :week_field, column, options, ui_options: ui_options
660
680
  end
661
681
 
662
682
  ##
@@ -695,8 +715,8 @@ module ActiveScaffold
695
715
  end
696
716
  alias override_input? override_input
697
717
 
698
- def subform_partial_for_column(column, klass = nil)
699
- subform_partial = "#{column.options[:layout] || active_scaffold_config_for(klass || column.association.klass).subform.layout}_subform"
718
+ def subform_partial_for_column(column, klass = nil, ui_options: column.options)
719
+ subform_partial = "#{ui_options[:layout] || active_scaffold_config_for(klass || column.association.klass).subform.layout}_subform"
700
720
  override_subform_partial(column, subform_partial) || subform_partial
701
721
  end
702
722
 
@@ -766,7 +786,7 @@ module ActiveScaffold
766
786
 
767
787
  # find minimum and maximum from validators
768
788
  # we can safely modify :min and :max by 1 for :greater_tnan or :less_than value only for integer values
769
- only_integer = column.column.type == :integer if column.column
789
+ only_integer = column.column_type == :integer if column.column
770
790
  only_integer ||= validators.find { |v| v.options[:only_integer] }.present?
771
791
  margin = only_integer ? 1 : 0
772
792
 
@@ -5,7 +5,7 @@ module ActiveScaffold
5
5
  def active_scaffold_human_condition_for(column)
6
6
  return if (value = field_search_params[column.name.to_s]).nil?
7
7
  search_ui = column.search_ui
8
- search_ui ||= column.column.type if column.column
8
+ search_ui ||= column.column_type if column.column
9
9
  if override_human_condition_column?(column)
10
10
  send(override_human_condition_column(column), value, {})
11
11
  elsif search_ui && override_human_condition?(search_ui)
@@ -26,6 +26,7 @@ module ActiveScaffold
26
26
  attribute = column.active_record_class.human_attribute_name(column.name)
27
27
  opt ||= :between if from && to
28
28
  opt ||= from ? '>=' : '<='
29
+ from = to = nil if opt&.in? %w[null not_null]
29
30
  "#{attribute} #{as_(opt).downcase} #{from} #{to}"
30
31
  end
31
32
 
@@ -37,28 +38,61 @@ module ActiveScaffold
37
38
  alias active_scaffold_human_condition_decimal active_scaffold_human_condition_integer
38
39
  alias active_scaffold_human_condition_float active_scaffold_human_condition_integer
39
40
 
40
- def active_scaffold_human_condition_string(column, value)
41
+ def active_scaffold_human_condition_range(column, value)
41
42
  opt = ActiveScaffold::Finder::STRING_COMPARATORS.key(value['opt']) || value['opt']
42
43
  to = "- #{value['to']}" if opt == 'BETWEEN'
43
44
  format_human_condition column, opt, "'#{value['from']}'", to
44
45
  end
46
+ alias active_scaffold_human_condition_string active_scaffold_human_condition_range
45
47
 
46
- def active_scaffold_human_condition_date(column, value)
47
- conversion = column.column.type == :date ? :to_date : :to_time
48
- from = controller.class.condition_value_for_datetime(column, value['from'], conversion)
49
- from = I18n.l from if from
50
- to = controller.class.condition_value_for_datetime(column, value['to'], conversion) if value['opt'] == 'BETWEEN' || (value['opt'].nil? && value['to'])
51
- to = "- #{I18n.l to}" if to
52
- format_human_condition column, value['opt'], from, to
48
+ def active_scaffold_human_condition_datetime(column, value)
49
+ case value['opt']
50
+ when 'RANGE'
51
+ range_type, range = value['range'].downcase.split('_')
52
+ format = active_scaffold_human_condition_datetime_range_format(range_type, range)
53
+ from, = controller.class.datetime_from_to(column, value)
54
+ "#{column.active_record_class.human_attribute_name(column.name)} = #{as_(value['range'].downcase).downcase} (#{I18n.l(from, :format => format)})"
55
+ when 'PAST', 'FUTURE'
56
+ from, to = controller.class.datetime_from_to(column, value)
57
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_('BETWEEN'.downcase).downcase} #{I18n.l(from)} - #{I18n.l(to)}"
58
+ else
59
+ from, to = controller.class.datetime_from_to(column, value)
60
+ "#{column.active_record_class.human_attribute_name(column.name)} #{as_(value['opt'].downcase).downcase} #{I18n.l(from)} #{value['opt'] == 'BETWEEN' ? '- ' + I18n.l(to) : ''}"
61
+ end
62
+ end
63
+ alias active_scaffold_human_condition_time active_scaffold_human_condition_datetime
64
+ alias active_scaffold_human_condition_date active_scaffold_human_condition_datetime
65
+ alias active_scaffold_human_condition_timestamp active_scaffold_human_condition_datetime
66
+
67
+ def active_scaffold_human_condition_datetime_range_format(range_type, range)
68
+ case range
69
+ when 'week'
70
+ first_day_of_week = I18n.translate 'active_scaffold.date_picker_options.firstDay'
71
+ if first_day_of_week == 1
72
+ '%W %Y'
73
+ else
74
+ '%U %Y'
75
+ end
76
+ when 'month'
77
+ '%b %Y'
78
+ when 'year'
79
+ '%Y'
80
+ else
81
+ I18n.translate 'date.formats.default'
82
+ end
53
83
  end
54
- alias active_scaffold_human_condition_time active_scaffold_human_condition_date
55
- alias active_scaffold_human_condition_datetime active_scaffold_human_condition_date
56
- alias active_scaffold_human_condition_timestamp active_scaffold_human_condition_date
84
+ # def active_scaffold_human_condition_date(column, value)
85
+ # conversion = column.column_type == :date ? :to_date : :to_time
86
+ # from = controller.class.condition_value_for_datetime(column, value['from'], conversion)
87
+ # from = I18n.l from if from
88
+ # to = controller.class.condition_value_for_datetime(column, value['to'], conversion) if value['opt'] == 'BETWEEN' || (value['opt'].nil? && value['to'])
89
+ # to = "- #{I18n.l to}" if to
90
+ # format_human_condition column, value['opt'], from, to
91
+ # end
57
92
 
58
93
  def active_scaffold_human_condition_boolean(column, value)
59
94
  attribute = column.active_record_class.human_attribute_name(column.name)
60
- label = as_(ActiveScaffold::Core.column_type_cast(value, column.column) ? :true : :false) # rubocop:disable Lint/BooleanSymbol
61
- as_(:boolean, :scope => :human_conditions, :column => attribute, :value => label)
95
+ as_(:boolean, :scope => :human_conditions, :column => attribute, :value => as_(value))
62
96
  end
63
97
  alias active_scaffold_human_condition_checkbox active_scaffold_human_condition_boolean
64
98