rails_admin 1.4.3 → 2.0.0.beta

Sign up to get free protection for your applications and to get access to all the features.

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|