rails_admin 1.4.3 → 2.0.0.beta

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.

Potentially problematic release.


This version of rails_admin might be problematic. Click here for more details.

Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +4 -1
  3. data/README.md +2 -4
  4. data/app/assets/javascripts/rails_admin/jquery.pjax.js +1 -3
  5. data/app/assets/javascripts/rails_admin/ra.filtering-select.js +9 -7
  6. data/app/assets/javascripts/rails_admin/ra.nested-form-hooks.coffee +1 -4
  7. data/app/assets/javascripts/rails_admin/ra.sidescroll.coffee +19 -0
  8. data/app/assets/javascripts/rails_admin/ra.widgets.coffee +35 -35
  9. data/app/assets/javascripts/rails_admin/rails_admin.js +1 -0
  10. data/app/assets/javascripts/rails_admin/ui.coffee +23 -18
  11. data/app/assets/stylesheets/rails_admin/ra.sidescroll.scss +29 -0
  12. data/app/assets/stylesheets/rails_admin/rails_admin.scss.erb +2 -1
  13. data/app/helpers/rails_admin/application_helper.rb +1 -1
  14. data/app/helpers/rails_admin/main_helper.rb +4 -4
  15. data/app/views/layouts/rails_admin/application.html.haml +0 -3
  16. data/app/views/layouts/rails_admin/pjax.html.haml +1 -5
  17. data/app/views/rails_admin/main/_form_action_text.html.haml +7 -0
  18. data/app/views/rails_admin/main/_form_file_upload.html.haml +1 -1
  19. data/app/views/rails_admin/main/_form_filtering_select.html.haml +1 -1
  20. data/app/views/rails_admin/main/_form_multiple_file_upload.html.haml +1 -1
  21. data/app/views/rails_admin/main/_form_polymorphic_association.html.haml +18 -3
  22. data/app/views/rails_admin/main/dashboard.html.haml +1 -2
  23. data/app/views/rails_admin/main/export.html.haml +2 -2
  24. data/app/views/rails_admin/main/index.html.haml +18 -14
  25. data/app/views/rails_admin/main/show.html.haml +6 -7
  26. data/config/locales/rails_admin.en.yml +1 -1
  27. data/lib/rails_admin/adapters/active_record.rb +10 -6
  28. data/lib/rails_admin/adapters/active_record/property.rb +1 -5
  29. data/lib/rails_admin/adapters/mongoid.rb +16 -13
  30. data/lib/rails_admin/bootstrap-sass.rb +4 -2
  31. data/lib/rails_admin/bootstrap-sass/sass_functions.rb +1 -3
  32. data/lib/rails_admin/config.rb +4 -0
  33. data/lib/rails_admin/config/actions/index.rb +3 -3
  34. data/lib/rails_admin/config/configurable.rb +5 -3
  35. data/lib/rails_admin/config/fields.rb +2 -0
  36. data/lib/rails_admin/config/fields/base.rb +1 -1
  37. data/lib/rails_admin/config/fields/factories/action_text.rb +12 -0
  38. data/lib/rails_admin/config/fields/factories/dragonfly.rb +1 -1
  39. data/lib/rails_admin/config/fields/factories/shrine.rb +27 -0
  40. data/lib/rails_admin/config/fields/types/action_text.rb +31 -0
  41. data/lib/rails_admin/config/fields/types/active_record_enum.rb +3 -19
  42. data/lib/rails_admin/config/fields/types/active_storage.rb +1 -0
  43. data/lib/rails_admin/config/fields/types/all.rb +2 -0
  44. data/lib/rails_admin/config/fields/types/ck_editor.rb +5 -5
  45. data/lib/rails_admin/config/fields/types/code_mirror.rb +8 -10
  46. data/lib/rails_admin/config/fields/types/froala.rb +7 -9
  47. data/lib/rails_admin/config/fields/types/shrine.rb +48 -0
  48. data/lib/rails_admin/config/fields/types/simple_mde.rb +6 -3
  49. data/lib/rails_admin/config/fields/types/text.rb +0 -18
  50. data/lib/rails_admin/config/fields/types/wysihtml5.rb +12 -8
  51. data/lib/rails_admin/config/model.rb +3 -2
  52. data/lib/rails_admin/config/proxyable.rb +13 -1
  53. data/lib/rails_admin/config/proxyable/proxy.rb +3 -5
  54. data/lib/rails_admin/config/sections/list.rb +23 -0
  55. data/lib/rails_admin/engine.rb +1 -2
  56. data/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +16 -4
  57. data/lib/rails_admin/version.rb +4 -4
  58. data/vendor/assets/fonts/rails_admin/FontAwesome.otf +0 -0
  59. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.eot +0 -0
  60. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.svg +2671 -0
  61. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.ttf +0 -0
  62. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.woff +0 -0
  63. data/vendor/assets/fonts/rails_admin/fontawesome-webfont.woff2 +0 -0
  64. data/vendor/assets/stylesheets/rails_admin/font-awesome.css.erb +2342 -0
  65. metadata +47 -32
@@ -1,9 +1,5 @@
1
- :javascript
2
- $('.nav.nav-pills li.active').removeClass('active');
3
- $('.nav.nav-pills li[data-model="#{@abstract_model.to_param}"]').addClass('active');
4
-
5
1
  %title= "#{@abstract_model.try(:pretty_name) || @page_name} | #{[_get_plugin_name[0] || 'Rails', _get_plugin_name[1] || 'Admin'].join(' ')}"
6
- .page-header
2
+ .page-header{data: {model: @abstract_model.to_param}}
7
3
  %h1= @page_name
8
4
  - flash && flash.each do |key, value|
9
5
  .alert.alert-dismissible{class: flash_alert_class(key)}
@@ -0,0 +1,7 @@
1
+ :ruby
2
+ js_data = {
3
+ csspath: field.css_location,
4
+ jspath: field.js_location
5
+ }
6
+
7
+ = form.rich_text_area field.method_name, field.html_attributes.reverse_merge(data: { options: js_data.to_json })
@@ -7,7 +7,7 @@
7
7
  = form.file_field(field.name, field.html_attributes.reverse_merge({ data: { fileupload: true }}))
8
8
 
9
9
  - if field.optional? && field.errors.blank? && file && field.delete_method
10
- %a.btn.btn-info.btn-remove-image{href: '#', :'data-toggle' => 'button', role: 'button', onclick: "$(this).siblings('[type=checkbox]').click(); $(this).siblings('.toggle').toggle('slow'); jQuery(this).toggleClass('btn-danger btn-info'); return false;"}
10
+ %a.btn.btn-info.btn-remove-image{href: '#', :'data-toggle' => 'button', role: 'button'}
11
11
  %i.icon-white.icon-trash
12
12
  = I18n.t('admin.actions.delete.menu').capitalize + " #{field.label.downcase}"
13
13
 
@@ -26,7 +26,7 @@
26
26
  }
27
27
 
28
28
  - selected_id = (hdv = field.form_default_value).nil? ? selected_id : hdv
29
- = form.select field.method_name, collection, { selected: selected_id, include_blank: true }, field.html_attributes.reverse_merge({ data: { filteringselect: true, options: js_data.to_json }, placeholder: t('admin.misc.search') })
29
+ = form.select field.method_name, collection, { selected: selected_id, include_blank: true }, field.html_attributes.reverse_merge({ data: { filteringselect: true, options: js_data.to_json }, placeholder: t('admin.misc.search'), style: "float: left" })
30
30
 
31
31
  - if authorized?(:new, config.abstract_model) && field.inline_add
32
32
  - path_hash = { model_name: config.abstract_model.to_param, modal: true }
@@ -2,7 +2,7 @@
2
2
  .toggle
3
3
  = attachment.pretty_value
4
4
  - if field.delete_method
5
- %a.btn.btn-info.btn-remove-image{href: '#', :'data-toggle' => 'button', role: 'button', onclick: "$(this).siblings('[type=checkbox]').click(); $(this).parent('.toggle').toggle('slow'); jQuery(this).toggleClass('btn-danger btn-info'); return false;"}
5
+ %a.btn.btn-info.btn-remove-image{href: '#', :'data-toggle' => 'button', role: 'button'}
6
6
  %i.icon-white.icon-trash
7
7
  = I18n.t('admin.actions.delete.menu').capitalize + " #{field.label.downcase} ##{i + 1}"
8
8
 
@@ -2,10 +2,25 @@
2
2
  type_collection = field.polymorphic_type_collection
3
3
  type_column = field.association.foreign_type.to_s
4
4
  selected_type = field.bindings[:object].send(type_column)
5
- collection = field.associated_collection(selected_type)
6
5
  selected = field.bindings[:object].send(field.association.name)
6
+ collection = selected ? [[field.formatted_value, selected.id]] : [[]]
7
7
  column_type_dom_id = form.dom_id(field).sub(field.method_name.to_s, type_column)
8
+ current_action = params[:action].in?(['create', 'new']) ? 'create' : 'update'
9
+
10
+ default_options = { float_left: false }
11
+
12
+ js_data = type_collection.inject({}) do |options, model|
13
+ model_name = model.second.underscore.downcase
14
+ source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
15
+ options.merge(model_name.gsub("_", "") => {
16
+ xhr: true,
17
+ remote_source: index_path(model_name, source_object_id: form.object.id, source_abstract_model: source_abstract_model.to_param, current_action: current_action, compact: true),
18
+ float_left: false
19
+ })
20
+ end
8
21
 
9
22
  .form-inline
10
- = form.select type_column, type_collection, {include_blank: true, selected: selected_type}, class: "form-control", id: column_type_dom_id, data: { polymorphic: true, urls: field.polymorphic_type_urls.to_json }
11
- = form.select field.method_name, collection, {include_blank: true, selected: selected.try(:id)}, class: "form-control"
23
+ - js_data.each do |model, value|
24
+ %div{id: "#{model}-js-options", data: { options: value.to_json } }
25
+ = form.select type_column, type_collection, {include_blank: true, selected: selected_type}, class: "form-control", id: column_type_dom_id, data: { polymorphic: true, urls: field.polymorphic_type_urls.to_json }, style: "float: left; margin-right: 10px;"
26
+ = form.select field.method_name, collection, {include_blank: true, selected: selected.try(:id)}, class: "form-control", data: { filteringselect: true, options: js_data[selected_type.try(:downcase)] || default_options }, placeholder: 'Search'
@@ -18,8 +18,7 @@
18
18
  %span.show= link_to capitalize_first_letter(abstract_model.config.label_plural), index_path, class: 'pjax'
19
19
  %td
20
20
  - if last_created
21
- = time_ago_in_words last_created
22
- = t "admin.misc.ago"
21
+ = t "admin.misc.time_ago", time: time_ago_in_words(last_created), default: "#{time_ago_in_words(last_created)} #{t("admin.misc.ago")}"
23
22
  %td
24
23
  - count = @count[abstract_model.model.name]
25
24
  - percent = count > 0 ? (@max <= 1 ? count : ((Math.log(count+1) * 100.0) / Math.log(@max+1)).to_i) : -1
@@ -16,7 +16,7 @@
16
16
  %b= t('admin.export.select_all_fields')
17
17
  .form-group.control-group
18
18
  .col-sm-12
19
- .well.well-sm{rel: 'tooltip', :'data-original-title' => t('admin.export.click_to_reverse_selection'), onclick: 'jQuery(this).closest(".control-group").find(".controls").find("input").click()', style: 'margin: 0; cursor: pointer;'}
19
+ .well.well-sm.reverse-selection{rel: 'tooltip', title: t('admin.export.click_to_reverse_selection'), style: 'margin: 0; cursor: pointer;'}
20
20
  %b= t('admin.export.fields_from', name: @model_config.label_plural.downcase)
21
21
  .controls
22
22
  .row
@@ -40,7 +40,7 @@
40
40
  - fields = field.associated_model_config.export.with(controller: self.controller, view: self, object: (associated_model = field.associated_model_config.abstract_model.model).new).visible_fields.select{ |f| !f.association? }
41
41
  .form-group.control-group
42
42
  .col-sm-12
43
- .well.well-sm{rel: 'tooltip', :'data-original-title' => t('admin.export.click_to_reverse_selection'), onclick: 'jQuery(this).closest(".control-group").find(".controls").find("input").click()', style: 'margin: 0; cursor: pointer;'}
43
+ .well.well-sm.reverse-selection{rel: 'tooltip', title: t('admin.export.click_to_reverse_selection'), style: 'margin: 0; cursor: pointer;'}
44
44
  %b= t('admin.export.fields_from_associated', name: field.label.downcase)
45
45
  .controls
46
46
  .row
@@ -12,10 +12,12 @@
12
12
  properties = @model_config.list.with(controller: self.controller, view: self, object: @abstract_model.model.new).visible_fields
13
13
  checkboxes = @model_config.list.checkboxes?
14
14
  # columns paginate
15
- sets = get_column_sets(properties)
16
- properties = sets[params[:set].to_i] || []
17
- other_left = ((params[:set].to_i - 1) >= 0) && sets[params[:set].to_i - 1].present?
18
- other_right = sets[params[:set].to_i + 1].present?
15
+ unless (frozen_columns = @model_config.list.sidescroll_frozen_columns)
16
+ sets = get_column_sets(properties)
17
+ properties = sets[params[:set].to_i] || []
18
+ other_left = ((params[:set].to_i - 1) >= 0) && sets[params[:set].to_i - 1].present?
19
+ other_right = sets[params[:set].to_i + 1].present?
20
+ end
19
21
 
20
22
  - content_for :contextual_tabs do
21
23
  - if checkboxes
@@ -35,11 +37,6 @@
35
37
  %li
36
38
  %a{href: '#', :"data-field-label" => field.label, :"data-field-name" => field.name, :"data-field-options" => field_options.html_safe, :"data-field-type" => field.type, :"data-field-value" => "", :"data-field-datetimepicker-format" => (field.try(:parser) && field.parser.to_momentjs)}= capitalize_first_letter(field.label)
37
39
 
38
- :javascript
39
- jQuery(function($) {
40
- #{ordered_filter_string}
41
- });
42
-
43
40
  %style
44
41
  - properties.select{ |p| p.column_width.present? }.each do |property|
45
42
  = "#list th.#{property.css_class} { width: #{property.column_width}px; min-width: #{property.column_width}px; }"
@@ -48,7 +45,7 @@
48
45
  #list
49
46
  = form_tag(index_path(params.except(*%w[page f query])), method: :get, class: "pjax-form form-inline") do
50
47
  .well
51
- %span#filters_box
48
+ %span#filters_box{data: {options: ordered_filter_options.to_json}}
52
49
  %hr.filters_box{style: "display:#{ordered_filters.empty? ? 'none' : 'block'}"}
53
50
  .input-group
54
51
  %input.form-control.input-small{name: "query", type: "search", value: query, placeholder: t("admin.misc.filter")}
@@ -68,7 +65,7 @@
68
65
  %li{class: "#{'active' if scope.to_s == params[:scope] || (params[:scope].blank? && index == 0)}"}
69
66
  %a{href: index_path(params.merge(scope: scope, page: nil)), class: 'pjax'}= I18n.t("admin.scopes.#{@abstract_model.to_param}.#{scope}", default: I18n.t("admin.scopes.#{scope}", default: scope.to_s.titleize))
70
67
 
71
- = form_tag bulk_action_path(model_name: @abstract_model.to_param), method: :post, id: "bulk_form", class: "form" do
68
+ = form_tag bulk_action_path(model_name: @abstract_model.to_param), method: :post, id: "bulk_form", class: ["form", frozen_columns ? 'ra-sidescroll' : nil], data: (frozen_columns ? {ra_sidescroll: frozen_columns} : {}) do
72
69
  = hidden_field_tag :bulk_action
73
70
  - if description.present?
74
71
  %p
@@ -80,6 +77,8 @@
80
77
  - if checkboxes
81
78
  %th.shrink
82
79
  %input.toggle{type: "checkbox"}
80
+ - if frozen_columns
81
+ %th.last.shrink
83
82
  - if other_left
84
83
  %th.other.left.shrink= "..."
85
84
  - properties.each do |property|
@@ -90,12 +89,16 @@
90
89
  %th{class: "#{property.sortable && "header pjax" || nil} #{sort_direction if property.sortable && sort_direction} #{property.css_class} #{property.type_css_class}", :'data-href' => (property.sortable && sort_location), rel: "tooltip", title: "#{property.hint}"}= capitalize_first_letter(property.label)
91
90
  - if other_right
92
91
  %th.other.right.shrink= "..."
93
- %th.last.shrink
92
+ - unless frozen_columns
93
+ %th.last.shrink
94
94
  %tbody
95
95
  - @objects.each do |object|
96
96
  %tr{class: "#{@abstract_model.param_key}_row #{@model_config.list.with(object: object).row_css_class}"}
97
97
  - if checkboxes
98
98
  %td= check_box_tag "bulk_ids[]", object.id, false
99
+ - if frozen_columns
100
+ %td.last.links
101
+ %ul.inline.list-inline= menu_for :member, @abstract_model, object, true
99
102
  - if @other_left_link ||= other_left && index_path(params.except('set').merge(params[:set].to_i != 1 ? {set: (params[:set].to_i - 1)} : {}))
100
103
  %td.other.left= link_to "...", @other_left_link, class: 'pjax'
101
104
  - properties.map{ |property| property.bind(:object, object) }.each do |property|
@@ -103,8 +106,9 @@
103
106
  %td{class: "#{property.css_class} #{property.type_css_class}", title: strip_tags(value.to_s)}= value
104
107
  - if @other_right_link ||= other_right && index_path(params.merge(set: (params[:set].to_i + 1)))
105
108
  %td.other.right= link_to "...", @other_right_link, class: 'pjax'
106
- %td.last.links
107
- %ul.inline.list-inline= menu_for :member, @abstract_model, object, true
109
+ - unless frozen_columns
110
+ %td.last.links
111
+ %ul.inline.list-inline= menu_for :member, @abstract_model, object, true
108
112
 
109
113
  - if @model_config.list.limited_pagination
110
114
  .row
@@ -1,6 +1,6 @@
1
1
  - @model_config.show.with(object: @object, view: self, controller: self.controller).visible_groups.each do |fieldset|
2
2
  - unless (fields = fieldset.with(object: @object, view: self, controller: self.controller).visible_fields).empty?
3
- - if !(values = fields.map{ |f| f.formatted_value.presence }).compact.empty? || !RailsAdmin::config.compact_show_view
3
+ - unless (fields = fields.reject{ |f| RailsAdmin::config.compact_show_view && f.formatted_value.nil? || f.formatted_value == '' }).empty?
4
4
  .fieldset
5
5
  %h4
6
6
  = fieldset.label
@@ -8,9 +8,8 @@
8
8
  %p= fieldset.help
9
9
  %dl
10
10
  - fields.each_with_index do |field, index|
11
- - unless values[index].nil? && RailsAdmin::config.compact_show_view
12
- %dt
13
- %span.label.label-info{class: "#{field.type_css_class} #{field.css_class}"}
14
- = field.label
15
- %dd.well
16
- = field.pretty_value
11
+ %dt
12
+ %span.label.label-info{class: "#{field.type_css_class} #{field.css_class}"}
13
+ = field.label
14
+ %dd.well
15
+ = field.pretty_value
@@ -43,7 +43,7 @@ en:
43
43
  navigation: "Navigation"
44
44
  navigation_static_label: "Links"
45
45
  log_out: "Log out"
46
- ago: "ago"
46
+ time_ago: "%{time} ago"
47
47
  more: "Plus %{count} more %{models_name}"
48
48
  flash:
49
49
  successful: "%{name} successfully %{action}"
@@ -118,13 +118,17 @@ module RailsAdmin
118
118
  end
119
119
 
120
120
  def query_scope(scope, query, fields = config.list.fields.select(&:queryable?))
121
- wb = WhereBuilder.new(scope)
122
- fields.each do |field|
123
- value = parse_field_value(field, query)
124
- wb.add(field, value, field.search_operator)
121
+ if config.list.search_by
122
+ scope.send(config.list.search_by, query)
123
+ else
124
+ wb = WhereBuilder.new(scope)
125
+ fields.each do |field|
126
+ value = parse_field_value(field, query)
127
+ wb.add(field, value, field.search_operator)
128
+ end
129
+ # OR all query statements
130
+ wb.build
125
131
  end
126
- # OR all query statements
127
- wb.build
128
132
  end
129
133
 
130
134
  # filters example => {"string_field"=>{"0055"=>{"o"=>"like", "v"=>"test_value"}}, ...}
@@ -48,11 +48,7 @@ module RailsAdmin
48
48
  private
49
49
 
50
50
  def serialized?
51
- if Rails.version < '4.2'
52
- model.serialized_attributes[property.name.to_s]
53
- else
54
- model.type_for_attribute(property.name).class == ::ActiveRecord::Type::Serialized
55
- end
51
+ model.type_for_attribute(property.name).class == ::ActiveRecord::Type::Serialized
56
52
  end
57
53
  end
58
54
  end
@@ -42,8 +42,8 @@ module RailsAdmin
42
42
  scope = scope.includes(*options[:include]) if options[:include]
43
43
  scope = scope.limit(options[:limit]) if options[:limit]
44
44
  scope = scope.any_in(_id: options[:bulk_ids]) if options[:bulk_ids]
45
- scope = scope.where(query_conditions(options[:query])) if options[:query]
46
- scope = scope.where(filter_conditions(options[:filters])) if options[:filters]
45
+ scope = query_scope(scope, options[:query]) if options[:query]
46
+ scope = filter_scope(scope, options[:filters]) if options[:filters]
47
47
  if options[:page] && options[:per]
48
48
  scope = scope.send(Kaminari.config.page_method_name, options[:page]).per(options[:per])
49
49
  end
@@ -104,7 +104,6 @@ module RailsAdmin
104
104
  conditions_per_collection = {}
105
105
  field.searchable_columns.each do |column_infos|
106
106
  collection_name, column_name = parse_collection_name(column_infos[:column])
107
- value = parse_field_value(field, value)
108
107
  statement = build_statement(column_name, column_infos[:type], value, operator)
109
108
  next unless statement
110
109
  conditions_per_collection[collection_name] ||= []
@@ -113,21 +112,25 @@ module RailsAdmin
113
112
  conditions_per_collection
114
113
  end
115
114
 
116
- def query_conditions(query, fields = config.list.fields.select(&:queryable?))
117
- statements = []
115
+ def query_scope(scope, query, fields = config.list.fields.select(&:queryable?))
116
+ if config.list.search_by
117
+ scope.send(config.list.search_by, query)
118
+ else
119
+ statements = []
118
120
 
119
- fields.each do |field|
120
- value = parse_field_value(field, query)
121
- conditions_per_collection = make_field_conditions(field, value, field.search_operator)
122
- statements.concat make_condition_for_current_collection(field, conditions_per_collection)
123
- end
121
+ fields.each do |field|
122
+ value = parse_field_value(field, query)
123
+ conditions_per_collection = make_field_conditions(field, value, field.search_operator)
124
+ statements.concat make_condition_for_current_collection(field, conditions_per_collection)
125
+ end
124
126
 
125
- statements.any? ? {'$or' => statements} : {}
127
+ scope.where(statements.any? ? {'$or' => statements} : {})
128
+ end
126
129
  end
127
130
 
128
131
  # filters example => {"string_field"=>{"0055"=>{"o"=>"like", "v"=>"test_value"}}, ...}
129
132
  # "0055" is the filter index, no use here. o is the operator, v the value
130
- def filter_conditions(filters, fields = config.list.fields.select(&:filterable?))
133
+ def filter_scope(scope, filters, fields = config.list.fields.select(&:filterable?))
131
134
  statements = []
132
135
 
133
136
  filters.each_pair do |field_name, filters_dump|
@@ -145,7 +148,7 @@ module RailsAdmin
145
148
  end
146
149
  end
147
150
 
148
- statements.any? ? {'$and' => statements} : {}
151
+ scope.where(statements.any? ? {'$and' => statements} : {})
149
152
  end
150
153
 
151
154
  def parse_collection_name(column)
@@ -17,8 +17,10 @@ module RailsAdmin
17
17
  raise(Bootstrap::FrameworkNotFound.new('bootstrap-sass requires either Rails > 3.1 or Compass, neither of which are loaded'))
18
18
  end
19
19
 
20
- stylesheets = File.expand_path(File.join('..', 'vendor', 'assets', 'stylesheets'))
21
- ::Sass.load_paths << stylesheets
20
+ if defined?(::Sass) && ::Sass.respond_to?(:load_paths)
21
+ stylesheets = File.expand_path(File.join('..', 'vendor', 'assets', 'stylesheets'))
22
+ ::Sass.load_paths << stylesheets
23
+ end
22
24
  end
23
25
 
24
26
  def self.asset_pipeline?
@@ -1,5 +1,3 @@
1
- require 'sass'
2
-
3
1
  module Sass
4
2
  module Script
5
3
  module Functions
@@ -12,7 +10,7 @@ module Sass
12
10
  alphastr = alpha.to_s(16).rjust(2, '0')
13
11
  Sass::Script::String.new("##{alphastr}#{color.send(:hex_str)[1..-1]}".upcase)
14
12
  end
15
- declare :ie_hex_str, [:color]
13
+ declare :ie_hex_str, [:color] if respond_to?(:declare)
16
14
  end
17
15
  end
18
16
  end
@@ -59,6 +59,9 @@ module RailsAdmin
59
59
  # Set the max width of columns in list view before a new set is created
60
60
  attr_accessor :total_columns_width
61
61
 
62
+ # Enable horizontal-scrolling table in list view, ignore total_columns_width
63
+ attr_accessor :sidescroll
64
+
62
65
  # set parent controller
63
66
  attr_accessor :parent_controller
64
67
 
@@ -285,6 +288,7 @@ module RailsAdmin
285
288
  @excluded_models = []
286
289
  @included_models = []
287
290
  @total_columns_width = 697
291
+ @sidescroll = nil
288
292
  @label_methods = [:name, :title]
289
293
  @main_app_name = proc { [Rails.application.engine_name.titleize.chomp(' Application'), 'Admin'] }
290
294
  @registry = {}
@@ -1,3 +1,5 @@
1
+ require 'activemodel-serializers-xml'
2
+
1
3
  module RailsAdmin
2
4
  module Config
3
5
  module Actions
@@ -76,10 +78,8 @@ module RailsAdmin
76
78
  send_data output,
77
79
  type: "text/csv; charset=#{encoding}; #{'header=present' if header}",
78
80
  disposition: "attachment; filename=#{params[:model_name]}_#{DateTime.now.strftime('%Y-%m-%d_%Hh%Mm%S')}.csv"
79
- elsif Rails.version.to_s >= '5'
80
- render plain: output
81
81
  else
82
- render text: output
82
+ render plain: output
83
83
  end
84
84
  end
85
85
  end
@@ -30,14 +30,16 @@ module RailsAdmin
30
30
  # and allows configurations such as
31
31
  # label { "#{label}".upcase }
32
32
  # This will use the default definition when called recursively.
33
- if instance_variable_get("@#{option_name}_recurring")
33
+ Thread.current[:rails_admin_recurring] ||= {}
34
+ Thread.current[:rails_admin_recurring][self] ||= {}
35
+ if Thread.current[:rails_admin_recurring][self][option_name]
34
36
  instance_eval(&default_proc)
35
37
  else
36
- instance_variable_set("@#{option_name}_recurring", true)
38
+ Thread.current[:rails_admin_recurring][self][option_name] = true
37
39
  instance_eval(&value_proc)
38
40
  end
39
41
  ensure
40
- instance_variable_set("@#{option_name}_recurring", false)
42
+ Thread.current[:rails_admin_recurring].delete(self)
41
43
  end
42
44
 
43
45
  module ClassMethods
@@ -84,4 +84,6 @@ require 'rails_admin/config/fields/factories/dragonfly'
84
84
  require 'rails_admin/config/fields/factories/carrierwave'
85
85
  require 'rails_admin/config/fields/factories/refile'
86
86
  require 'rails_admin/config/fields/factories/active_storage'
87
+ require 'rails_admin/config/fields/factories/shrine'
88
+ require 'rails_admin/config/fields/factories/action_text'
87
89
  require 'rails_admin/config/fields/factories/association'
@@ -20,7 +20,7 @@ module RailsAdmin
20
20
 
21
21
  NAMED_INSTANCE_VARIABLES = [
22
22
  :@parent, :@root, :@section, :@children_fields_registered,
23
- :@associated_model_config, :@group, :@bindings
23
+ :@associated_model_config, :@group
24
24
  ].freeze
25
25
 
26
26
  def initialize(parent, name, properties)
@@ -0,0 +1,12 @@
1
+ require 'rails_admin/config/fields'
2
+ require 'rails_admin/config/fields/types'
3
+
4
+ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
5
+ if defined?(::ActionText) && properties.try(:association?) && (match = /\Arich_text_(.+)\Z/.match properties.name) && properties.klass.to_s == 'ActionText::RichText'
6
+ field = RailsAdmin::Config::Fields::Types.load(:action_text).new(parent, match[1], properties)
7
+ fields << field
8
+ true
9
+ else
10
+ false
11
+ end
12
+ end
@@ -4,7 +4,7 @@ require 'rails_admin/config/fields/types/file_upload'
4
4
 
5
5
  RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
6
6
  extensions = [:name, :uid]
7
- if (properties.name.to_s =~ /^(.+)_uid$/) && defined?(::Dragonfly) && parent.abstract_model.model.dragonfly_attachment_classes.collect(&:attribute).include?(attachment_name = Regexp.last_match[1].to_sym)
7
+ if (properties.name.to_s =~ /^(.+)_uid$/) && defined?(::Dragonfly) && parent.abstract_model.model.respond_to?(:dragonfly_attachment_classes) && parent.abstract_model.model.dragonfly_attachment_classes.collect(&:attribute).include?(attachment_name = Regexp.last_match[1].to_sym)
8
8
  field = RailsAdmin::Config::Fields::Types.load(:dragonfly).new(parent, attachment_name, properties)
9
9
  children_fields = []
10
10
  extensions.each do |ext|