active_scaffold 3.7.0 → 3.7.1

Sign up to get free protection for your applications and to get access to all the features.
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