rails_admin 3.0.0.rc2 → 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -7
  3. data/app/controllers/rails_admin/main_controller.rb +2 -3
  4. data/app/helpers/rails_admin/application_helper.rb +33 -11
  5. data/app/views/layouts/rails_admin/_head.html.erb +8 -5
  6. data/app/views/layouts/rails_admin/_secondary_navigation.html.erb +2 -2
  7. data/app/views/layouts/rails_admin/application.html.erb +1 -1
  8. data/app/views/rails_admin/main/export.html.erb +1 -1
  9. data/app/views/rails_admin/main/history.html.erb +1 -1
  10. data/app/views/rails_admin/main/index.html.erb +2 -2
  11. data/app/views/rails_admin/main/show.html.erb +11 -9
  12. data/lib/generators/rails_admin/install_generator.rb +2 -4
  13. data/lib/rails_admin/abstract_model.rb +2 -3
  14. data/lib/rails_admin/adapters/active_record.rb +2 -1
  15. data/lib/rails_admin/adapters/mongoid.rb +2 -2
  16. data/lib/rails_admin/config/actions/base.rb +5 -0
  17. data/lib/rails_admin/config/actions/export.rb +2 -1
  18. data/lib/rails_admin/config/actions/index.rb +2 -1
  19. data/lib/rails_admin/config/actions/new.rb +2 -1
  20. data/lib/rails_admin/config/actions/show_in_app.rb +4 -0
  21. data/lib/rails_admin/config/fields/base.rb +2 -2
  22. data/lib/rails_admin/config/fields/factories/active_storage.rb +2 -1
  23. data/lib/rails_admin/config/fields/factories/association.rb +4 -4
  24. data/lib/rails_admin/config/fields/factories/carrierwave.rb +2 -1
  25. data/lib/rails_admin/config/fields/factories/devise.rb +2 -1
  26. data/lib/rails_admin/config/fields/factories/dragonfly.rb +2 -1
  27. data/lib/rails_admin/config/fields/factories/paperclip.rb +2 -1
  28. data/lib/rails_admin/config/fields/types/datetime.rb +2 -1
  29. data/lib/rails_admin/config.rb +1 -1
  30. data/lib/rails_admin/engine.rb +6 -7
  31. data/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +2 -2
  32. data/lib/rails_admin/extensions/pundit/authorization_adapter.rb +1 -1
  33. data/lib/rails_admin/version.rb +34 -1
  34. data/package.json +1 -1
  35. data/src/rails_admin/ui.js +11 -2
  36. data/vendor/assets/javascripts/rails_admin/flatpickr-with-locales.js +958 -395
  37. metadata +5 -5
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 142382cf0987b581cb64996e716ad77cf9ae76dab5aa1bf019b8ca38fb7daed0
4
- data.tar.gz: 58a52e67fc458713f0245ea244e2a129f370309edc91511678ba06bbc756e9cc
3
+ metadata.gz: a20d0a9cc9b7702c63e5e92918ac89f986b2d3d1e666539fd0c16562508bdf85
4
+ data.tar.gz: 7d5784f25b6a16c0d2a05b827a8bc9990da28d056d34b2569ea628910088ae89
5
5
  SHA512:
6
- metadata.gz: 55fce15b0a7bf4f168b042ab7415fd24f0cefdb509d61efdb2f3f15de42b657bbbe24b62e686a359f18239f0c9ad36436bbd229c22b35c28be17d8f27fb5ef7f
7
- data.tar.gz: 9d076ac618ecdbb0680e7d8e7dd3472b7d0e47d10d5d12b4bdfc260c43297ded2e430a410926d0a680cbe120406e20da3678b5adb5ef2050efebe9aa8e2f8e12
6
+ metadata.gz: ea7b4265126ff76473d461cd0630feb1a4e3ad71476d2843577a25fdaea53fed0ca57b06b55dbe63615f5004151796b346f9bca2492ff71175d44faffbe24c38
7
+ data.tar.gz: 58fb832bd8e1e7c124e79eabd01393da73217714e0b52a32ea215ef1e1b2d4f33390928ed15686eeed983446d74a914ac947cd709bd67180799bf8bd9017bc4a
data/README.md CHANGED
@@ -14,12 +14,6 @@
14
14
 
15
15
  RailsAdmin is a Rails engine that provides an easy-to-use interface for managing your data.
16
16
 
17
- ## Announcements
18
-
19
- ### [Action required] Security issue
20
-
21
- **RailsAdmin 2.0.1, 2.0.0 and up to 1.4.2 have been reported to have XSS vulnerability.** We strongly recommend that you upgrade RailsAdmin to 2.0.2 (and higher) or 1.4.3 as soon as possible, if you are on those versions. See [d72090ec](https://github.com/railsadminteam/rails_admin/commit/d72090ec6a07c3b9b7b48ab50f3d405f91ff4375) for the detail.
22
-
23
17
  ## Getting started
24
18
 
25
19
  - Check out [the docs][docs].
@@ -45,7 +39,7 @@ RailsAdmin is a Rails engine that provides an easy-to-use interface for managing
45
39
 
46
40
  ## Installation
47
41
 
48
- 1. On your gemfile: `gem 'rails_admin', ['>= 3.0.0.rc2', '< 4']`
42
+ 1. On your gemfile: `gem 'rails_admin', '~> 3.0'`
49
43
  2. Run `bundle install`
50
44
  3. Run `rails g rails_admin:install`
51
45
  4. Provide a namespace for the routes when asked
@@ -13,9 +13,8 @@ module RailsAdmin
13
13
 
14
14
  def list_entries(model_config = @model_config, auth_scope_key = :index, additional_scope = get_association_scope_from_params, pagination = !(params[:associated_collection] || params[:all] || params[:bulk_ids]))
15
15
  scope = model_config.scope
16
- if auth_scope = @authorization_adapter&.query(auth_scope_key, model_config.abstract_model)
17
- scope = scope.merge(auth_scope)
18
- end
16
+ auth_scope = @authorization_adapter&.query(auth_scope_key, model_config.abstract_model)
17
+ scope = scope.merge(auth_scope) if auth_scope
19
18
  scope = scope.instance_eval(&additional_scope) if additional_scope
20
19
  get_collection(model_config, scope, pagination)
21
20
  end
@@ -20,17 +20,24 @@ module RailsAdmin
20
20
  end
21
21
 
22
22
  def edit_user_link
23
- return nil unless _current_user.respond_to?(:email)
24
- return nil unless abstract_model = RailsAdmin.config(_current_user.class).abstract_model
25
-
26
- content = [
27
- RailsAdmin::Config.show_gravatar && _current_user.email.present? && image_tag("#{request.ssl? ? 'https://secure' : 'http://www'}.gravatar.com/avatar/#{Digest::MD5.hexdigest _current_user.email}?s=30", alt: ''),
28
- content_tag(:span, _current_user.email),
29
- ].compact.join.html_safe
30
- if (edit_action = RailsAdmin::Config::Actions.find(:edit, controller: controller, abstract_model: abstract_model, object: _current_user)).try(:authorized?)
31
- link_to content, rails_admin.url_for(action: edit_action.action_name, model_name: abstract_model.to_param, id: _current_user.id, controller: 'rails_admin/main'), class: 'nav-link'
23
+ return nil unless _current_user.try(:email).present?
24
+ return nil unless (abstract_model = RailsAdmin.config(_current_user.class).abstract_model)
25
+
26
+ edit_action = action(:edit, abstract_model, _current_user)
27
+ authorized = edit_action.try(:authorized?)
28
+ content = edit_user_link_label
29
+
30
+ if authorized
31
+ edit_url = rails_admin.url_for(
32
+ action_name: edit_action.action_name,
33
+ model_name: abstract_model.to_param,
34
+ controller: 'rails_admin/main',
35
+ id: _current_user.id,
36
+ )
37
+
38
+ link_to content, edit_url, class: 'nav-link'
32
39
  else
33
- content_tag :span, content
40
+ content_tag :span, content, class: 'nav-link'
34
41
  end
35
42
  end
36
43
 
@@ -162,7 +169,7 @@ module RailsAdmin
162
169
  else
163
170
  'javascript:void(0)'
164
171
  end
165
- content_tag(:a, label, {href: href, target: action.link_target, class: ['nav-link', current_action?(action) && 'active', !action.enabled? && 'disabled'].compact})
172
+ content_tag(:a, label, {href: href, target: action.link_target, class: ['nav-link', current_action?(action) && 'active', !action.enabled? && 'disabled'].compact}.merge(action.turbo? ? {} : {data: {turbo: 'false'}}))
166
173
  else
167
174
  content_tag(:span, label)
168
175
  end
@@ -206,5 +213,20 @@ module RailsAdmin
206
213
  end
207
214
  raise e
208
215
  end
216
+
217
+ private
218
+
219
+ def edit_user_link_label
220
+ [
221
+ RailsAdmin::Config.show_gravatar &&
222
+ image_tag(gravatar_url(_current_user.email), alt: ''),
223
+
224
+ content_tag(:span, _current_user.email),
225
+ ].filter(&:present?).join.html_safe
226
+ end
227
+
228
+ def gravatar_url(email)
229
+ "https://secure.gravatar.com/avatar/#{Digest::MD5.hexdigest email}?s=30"
230
+ end
209
231
  end
210
232
  end
@@ -5,13 +5,16 @@
5
5
  <%= csrf_meta_tag %>
6
6
  <% case RailsAdmin::config.asset_source
7
7
  when :webpacker %>
8
- <%= stylesheet_pack_tag "rails_admin" %>
9
- <%= javascript_pack_tag "rails_admin", async: true %>
10
- <% when :webpack, :sprockets %>
8
+ <%= stylesheet_pack_tag "rails_admin", data: {'turbo-track': 'reload'} %>
9
+ <%= javascript_pack_tag "rails_admin", async: true, data: {'turbo-track': 'reload'} %>
10
+ <% when :sprockets %>
11
11
  <% handle_asset_dependency_error do %>
12
- <%= stylesheet_link_tag "rails_admin/application.css", media: :all %>
13
- <%= javascript_include_tag "rails_admin/application.js", async: true %>
12
+ <%= stylesheet_link_tag "rails_admin/application.css", media: :all, data: {'turbo-track': 'reload'} %>
13
+ <%= javascript_include_tag "rails_admin/application.js", async: true, data: {'turbo-track': 'reload'} %>
14
14
  <% end %>
15
+ <% when :webpack %>
16
+ <%= stylesheet_link_tag "rails_admin.css", media: :all, data: {'turbo-track': 'reload'} %>
17
+ <%= javascript_include_tag "rails_admin.js", async: true, data: {'turbo-track': 'reload'} %>
15
18
  <% else
16
19
  raise "Unknown asset_source: #{RailsAdmin::config.asset_source}"
17
20
  end %>
@@ -1,7 +1,7 @@
1
1
  <ul class="navbar-nav ms-auto root_links">
2
2
  <% actions(:root).select(&:show_in_navigation).each do |action| %>
3
3
  <li class="nav-item <%= action.action_name %>_root_link">
4
- <%= link_to wording_for(:menu, action), { action: action.action_name, controller: 'rails_admin/main' }, class: ['nav-link'] %>
4
+ <%= link_to wording_for(:menu, action), { action: action.action_name, controller: 'rails_admin/main' }, {class: ['nav-link']}.merge(action.turbo? ? {} : {data: {turbo: 'false'}}) %>
5
5
  </li>
6
6
  <% end %>
7
7
  <% if main_app_root_path = (main_app.root_path rescue false) %>
@@ -17,7 +17,7 @@
17
17
  <% end %>
18
18
  <% if logout_path.present? %>
19
19
  <li class="nav-item">
20
- <%= link_to t('admin.misc.log_out'), logout_path, method: logout_method, class: 'nav-link label label-danger' %>
20
+ <%= link_to t('admin.misc.log_out'), logout_path, method: logout_method, class: 'nav-link label label-danger', data: {turbo: 'false'} %>
21
21
  </li>
22
22
  <% end %>
23
23
  <% end %>
@@ -14,7 +14,7 @@
14
14
  <%= render "layouts/rails_admin/sidebar_navigation" %>
15
15
  </div>
16
16
  <div class="col-sm-9 col-sm-offset-3 col-md-10 col-md-offset-2">
17
- <div class="container">
17
+ <div class="container-fluid">
18
18
  <%= render template: 'layouts/rails_admin/content' %>
19
19
  </div>
20
20
  </div>
@@ -1,6 +1,6 @@
1
1
  <% params = request.params.except(:action, :controller, :utf8, :page, :per_page, :format, :authenticity_token) %>
2
2
  <% visible_fields = @model_config.export.with(view: self, object: @abstract_model.model.new, controller: self.controller).visible_fields %>
3
- <%= form_tag export_path(params.merge(all: true)), method: 'post', class: "main" do %>
3
+ <%= form_tag export_path(params.merge(all: true)), method: 'post', class: "main", data: {turbo: false} do %>
4
4
  <input name="send_data" type="hidden" value="true" />
5
5
  <fieldset id="fields_to_export" class="mb-3">
6
6
  <legend>
@@ -32,7 +32,7 @@
32
32
  <% selected = (sort == property_name) %>
33
33
  <% sort_direction = (sort_reverse ? "headerSortUp" : "headerSortDown" if selected) %>
34
34
  <% sort_location = send(path_method, params.except("sort_reverse").merge(model_name: @abstract_model.to_param, sort: property_name).merge(selected && sort_reverse != "true" ? {sort_reverse: "true"} : {})) %>
35
- <th class="header <%= column[:css_class] %> <%= sort_direction if selected %>">
35
+ <th class="header <%= column[:css_class] %> <%= sort_direction if selected %>" data-href="<%= sort_location %>">
36
36
  <%= column[:link_text] %>
37
37
  </th>
38
38
  <% end %>
@@ -96,8 +96,8 @@
96
96
  <ul class="nav nav-tabs" id="scope_selector">
97
97
  <% @model_config.list.scopes.each_with_index do |scope, index| %>
98
98
  <% scope = '_all' if scope.nil? %>
99
- <li class="<%= 'active' if scope.to_s == params[:scope] || (params[:scope].blank? && index == 0) %>">
100
- <a href="<%= index_path(params.merge(scope: scope, page: nil)) %>">
99
+ <li class="nav-item">
100
+ <a href="<%= index_path(params.merge(scope: scope, page: nil)) %>" class="nav-link <%= 'active' if scope.to_s == params[:scope] || (params[:scope].blank? && index == 0) %>">
101
101
  <%= I18n.t("admin.scopes.#{@abstract_model.to_param}.#{scope}", default: I18n.t("admin.scopes.#{scope}", default: scope.to_s.titleize)) %>
102
102
  </a>
103
103
  </li>
@@ -10,16 +10,18 @@
10
10
  <%= fieldset.help %>
11
11
  </p>
12
12
  <% end %>
13
- <dl>
13
+ <div class="list-group">
14
14
  <% fields.each_with_index do |field, index| %>
15
- <dt>
16
- <span class="<%= field.type_css_class %> <%= field.css_class %> label label-info">
17
- <%= field.label %>
18
- </span>
19
- </dt>
20
- <dd class="well">
21
- <%= field.pretty_value %>
22
- </dd>
15
+ <div class="list-group-item border-0 <%= field.type_css_class %> <%= field.css_class %>">
16
+ <div class="card">
17
+ <h5 class="card-header bg-light">
18
+ <%= field.label %>
19
+ </h5>
20
+ <div class="card-body">
21
+ <%= field.pretty_value %>
22
+ </div>
23
+ </div>
24
+ </div>
23
25
  <% end %>
24
26
  </dl>
25
27
  </div>
@@ -8,7 +8,7 @@ module RailsAdmin
8
8
  include Generators::Utils::InstanceMethods
9
9
 
10
10
  argument :_namespace, type: :string, required: false, desc: 'RailsAdmin url namespace'
11
- class_option :asset, type: :string, required: false, default: nil, desc: 'Asset delivery method [options: webpack, webpacker, sprockets]'
11
+ class_option :asset, type: :string, required: false, default: nil, desc: 'Asset delivery method [options: webpacker, sprockets]'
12
12
  desc 'RailsAdmin installation generator'
13
13
 
14
14
  def install
@@ -39,9 +39,7 @@ module RailsAdmin
39
39
  def asset
40
40
  return options['asset'] if options['asset']
41
41
 
42
- if Rails.root.join('webpack.config.js').exist?
43
- 'webpack'
44
- elsif defined?(Webpacker)
42
+ if defined?(Webpacker)
45
43
  'webpacker'
46
44
  else
47
45
  'sprockets'
@@ -86,9 +86,8 @@ module RailsAdmin
86
86
  associations.each do |association|
87
87
  case association.type
88
88
  when :has_one
89
- if child = object.send(association.name)
90
- yield(association, [child])
91
- end
89
+ child = object.send(association.name)
90
+ yield(association, [child]) if child
92
91
  when :has_many
93
92
  children = object.send(association.name)
94
93
  yield(association, Array.new(children))
@@ -13,7 +13,8 @@ module RailsAdmin
13
13
  end
14
14
 
15
15
  def get(id, scope = scoped)
16
- return unless object = scope.where(primary_key => id).first
16
+ object = scope.where(primary_key => id).first
17
+ return unless object
17
18
 
18
19
  object.extend(ObjectExtension)
19
20
  end
@@ -52,10 +52,10 @@ module RailsAdmin
52
52
  scope
53
53
  rescue NoMethodError => e
54
54
  if /page/.match?(e.message)
55
- e = e.exception <<-EOM.gsub(/^\s{12}/, '')
55
+ e = e.exception <<-ERROR.gsub(/^\s{12}/, '')
56
56
  #{e.message}
57
57
  If you don't have kaminari-mongoid installed, add `gem 'kaminari-mongoid'` to your Gemfile.
58
- EOM
58
+ ERROR
59
59
  end
60
60
  raise e
61
61
  end
@@ -78,6 +78,11 @@ module RailsAdmin
78
78
  nil
79
79
  end
80
80
 
81
+ # Determines whether to navigate via Turbo Drive or not
82
+ register_instance_option :turbo? do
83
+ true
84
+ end
85
+
81
86
  # This block is evaluated in the context of the controller when action is called
82
87
  # You can access:
83
88
  # - @objects if you're on a model scope
@@ -14,7 +14,8 @@ module RailsAdmin
14
14
 
15
15
  register_instance_option :controller do
16
16
  proc do
17
- if format = params[:json] && :json || params[:csv] && :csv || params[:xml] && :xml
17
+ format = params[:json] && :json || params[:csv] && :csv || params[:xml] && :xml
18
+ if format
18
19
  request.format = format
19
20
  @schema = HashHelper.symbolize(params[:schema].slice(:except, :include, :methods, :only).permit!.to_h) if params[:schema] # to_json and to_xml expect symbols for keys AND values.
20
21
  @objects = list_entries(@model_config, :export)
@@ -20,7 +20,8 @@ module RailsAdmin
20
20
 
21
21
  register_instance_option :breadcrumb_parent do
22
22
  parent_model = bindings[:abstract_model].try(:config).try(:parent)
23
- if am = parent_model && RailsAdmin.config(parent_model).try(:abstract_model)
23
+ am = parent_model && RailsAdmin.config(parent_model).try(:abstract_model)
24
+ if am
24
25
  [:index, am]
25
26
  else
26
27
  [:dashboard]
@@ -21,7 +21,8 @@ module RailsAdmin
21
21
  @authorization_adapter&.attributes_for(:new, @abstract_model)&.each do |name, value|
22
22
  @object.send("#{name}=", value)
23
23
  end
24
- if object_params = params[@abstract_model.param_key]
24
+ object_params = params[@abstract_model.param_key]
25
+ if object_params
25
26
  sanitize_params_for!(request.xhr? ? :modal : :create)
26
27
  @object.assign_attributes(@object.attributes.merge(object_params.to_h))
27
28
  end
@@ -25,6 +25,10 @@ module RailsAdmin
25
25
  register_instance_option :link_icon do
26
26
  'fas fa-eye'
27
27
  end
28
+
29
+ register_instance_option :turbo? do
30
+ false
31
+ end
28
32
  end
29
33
  end
30
34
  end
@@ -301,14 +301,14 @@ module RailsAdmin
301
301
  def value
302
302
  bindings[:object].safe_send(name)
303
303
  rescue NoMethodError => e
304
- raise e.exception <<-EOM.gsub(/^\s{10}/, '')
304
+ raise e.exception <<-ERROR.gsub(/^\s{10}/, '')
305
305
  #{e.message}
306
306
  If you want to use a RailsAdmin virtual field(= a field without corresponding instance method),
307
307
  you should declare 'formatted_value' in the field definition.
308
308
  field :#{name} do
309
309
  formatted_value{ bindings[:object].call_some_method }
310
310
  end
311
- EOM
311
+ ERROR
312
312
  end
313
313
 
314
314
  # Reader for nested attributes
@@ -16,7 +16,8 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
16
16
  ["#{name}_attachment".to_sym, "#{name}_blob".to_sym]
17
17
  end
18
18
  children_fields = associations.map do |child_name|
19
- next unless child_association = parent.abstract_model.associations.detect { |p| p.name.to_sym == child_name }
19
+ child_association = parent.abstract_model.associations.detect { |p| p.name.to_sym == child_name }
20
+ next unless child_association
20
21
 
21
22
  child_field = fields.detect { |f| f.name == child_name } || RailsAdmin::Config::Fields.default_factory.call(parent, child_association, fields)
22
23
  child_field.hide unless field == child_field
@@ -3,7 +3,8 @@ require 'rails_admin/config/fields/types'
3
3
  require 'rails_admin/config/fields/types/belongs_to_association'
4
4
 
5
5
  RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
6
- if association = parent.abstract_model.associations.detect { |a| a.foreign_key == properties.name && %i[belongs_to has_and_belongs_to_many].include?(a.type) }
6
+ association = parent.abstract_model.associations.detect { |a| a.foreign_key == properties.name && %i[belongs_to has_and_belongs_to_many].include?(a.type) }
7
+ if association
7
8
  field = RailsAdmin::Config::Fields::Types.load("#{association.polymorphic? ? :polymorphic : association.type}_association").new(parent, association.name, association)
8
9
  fields << field
9
10
 
@@ -15,9 +16,8 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
15
16
  end.collect { |k| association.send(k) }.compact
16
17
 
17
18
  parent.abstract_model.properties.select { |p| possible_field_names.include? p.name }.each do |column|
18
- unless child_field = fields.detect { |f| f.name.to_s == column.name.to_s }
19
- child_field = RailsAdmin::Config::Fields.default_factory.call(parent, column, fields)
20
- end
19
+ child_field = fields.detect { |f| f.name.to_s == column.name.to_s }
20
+ child_field ||= RailsAdmin::Config::Fields.default_factory.call(parent, column, fields)
21
21
  child_columns << child_field
22
22
  end
23
23
 
@@ -12,7 +12,8 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
12
12
  fields << field
13
13
  children_fields = []
14
14
  columns.each do |children_column_name|
15
- next unless child_properties = parent.abstract_model.properties.detect { |p| p.name.to_s == children_column_name.to_s }
15
+ child_properties = parent.abstract_model.properties.detect { |p| p.name.to_s == children_column_name.to_s }
16
+ next unless child_properties
16
17
 
17
18
  children_field = fields.detect { |f| f.name == children_column_name } || RailsAdmin::Config::Fields.default_factory.call(parent, child_properties, fields)
18
19
  children_field.hide unless field == children_field
@@ -12,7 +12,8 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
12
12
  properties = parent.abstract_model.properties.detect { |p| ext == p.name }
13
13
  next unless properties
14
14
 
15
- unless field = fields.detect { |f| f.name == ext }
15
+ field = fields.detect { |f| f.name == ext }
16
+ unless field
16
17
  RailsAdmin::Config::Fields.default_factory.call(parent, properties, fields)
17
18
  field = fields.last
18
19
  end
@@ -9,7 +9,8 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
9
9
  children_fields = []
10
10
  extensions.each do |ext|
11
11
  children_column_name = "#{attachment_name}_#{ext}".to_sym
12
- next unless child_properties = parent.abstract_model.properties.detect { |p| p.name.to_s == children_column_name.to_s }
12
+ child_properties = parent.abstract_model.properties.detect { |p| p.name.to_s == children_column_name.to_s }
13
+ next unless child_properties
13
14
 
14
15
  children_field = fields.detect { |f| f.name == children_column_name } || RailsAdmin::Config::Fields.default_factory.call(parent, child_properties, fields)
15
16
  children_field.hide
@@ -10,7 +10,8 @@ RailsAdmin::Config::Fields.register_factory do |parent, properties, fields|
10
10
  children_fields = []
11
11
  extensions.each do |ext|
12
12
  children_column_name = "#{attachment_name}_#{ext}".to_sym
13
- next unless child_properties = parent.abstract_model.properties.detect { |p| p.name.to_s == children_column_name.to_s }
13
+ child_properties = parent.abstract_model.properties.detect { |p| p.name.to_s == children_column_name.to_s }
14
+ next unless child_properties
14
15
 
15
16
  children_field = fields.detect { |f| f.name == children_column_name } || RailsAdmin::Config::Fields.default_factory.call(parent, child_properties, fields)
16
17
  children_field.hide
@@ -58,7 +58,8 @@ module RailsAdmin
58
58
  end
59
59
 
60
60
  register_instance_option :formatted_value do
61
- if time = (value || default_value)
61
+ time = (value || default_value)
62
+ if time
62
63
  ::I18n.l(time, format: strftime_format)
63
64
  else
64
65
  ''.html_safe
@@ -39,7 +39,7 @@ module RailsAdmin
39
39
  attr_accessor :included_models
40
40
 
41
41
  # Fields to be hidden in show, create and update views
42
- attr_accessor :default_hidden_fields
42
+ attr_reader :default_hidden_fields
43
43
 
44
44
  # Default items per page value used if a model level option has not
45
45
  # been configured
@@ -2,6 +2,7 @@ require 'kaminari'
2
2
  require 'nested_form'
3
3
  require 'rails'
4
4
  require 'rails_admin'
5
+ require 'rails_admin/version'
5
6
  require 'turbo-rails'
6
7
 
7
8
  module RailsAdmin
@@ -11,7 +12,7 @@ module RailsAdmin
11
12
  config.action_dispatch.rescue_responses['RailsAdmin::ActionNotAllowed'] = :forbidden
12
13
 
13
14
  initializer 'RailsAdmin precompile hook', group: :all do |app|
14
- if app.config.respond_to?(:assets)
15
+ if defined?(Sprockets)
15
16
  app.config.assets.precompile += %w[
16
17
  rails_admin/application.js
17
18
  rails_admin/application.css
@@ -42,10 +43,6 @@ module RailsAdmin
42
43
  end
43
44
  end
44
45
 
45
- rake_tasks do
46
- Dir[File.join(File.dirname(__FILE__), '../tasks/*.rake')].each { |f| load f }
47
- end
48
-
49
46
  # Check for required middlewares, users may forget to use them in Rails API mode
50
47
  config.after_initialize do |app|
51
48
  has_session_store = app.config.middleware.to_a.any? do |m|
@@ -59,20 +56,22 @@ module RailsAdmin
59
56
  unless missing.empty? && has_session_store
60
57
  configs = missing.map { |m| "config.middleware.use #{m}" }
61
58
  configs << "config.middleware.use #{app.config.session_store.try(:name) || 'ActionDispatch::Session::CookieStore'}, #{app.config.session_options}" unless has_session_store
62
- raise <<~EOM
59
+ raise <<~ERROR
63
60
  Required middlewares for RailsAdmin are not added
64
61
  To fix this, add
65
62
 
66
63
  #{configs.join("\n ")}
67
64
 
68
65
  to config/application.rb.
69
- EOM
66
+ ERROR
70
67
  end
71
68
 
72
69
  RailsAdmin::Config.initialize!
73
70
 
74
71
  # Force route reload, since it doesn't reflect RailsAdmin action configuration yet
75
72
  app.reload_routes!
73
+
74
+ RailsAdmin::Version.warn_with_js_version
76
75
  end
77
76
  end
78
77
  end
@@ -49,7 +49,7 @@ module RailsAdmin
49
49
  created_at: :created_at,
50
50
  message: :event,
51
51
  }.freeze
52
- E_VERSION_MODEL_NOT_SET = <<-EOS.strip_heredoc.freeze
52
+ E_VERSION_MODEL_NOT_SET = <<-ERROR.strip_heredoc.freeze
53
53
  Please set up PaperTrail's version model explicitly.
54
54
 
55
55
  config.audit_with :paper_trail, 'User', 'PaperTrail::Version'
@@ -58,7 +58,7 @@ module RailsAdmin
58
58
  (https://github.com/paper-trail-gem/paper_trail#6a-custom-version-classes)
59
59
  that configuration will take precedence over what you specify in
60
60
  `audit_with`.
61
- EOS
61
+ ERROR
62
62
 
63
63
  def self.setup
64
64
  raise 'PaperTrail not found' unless defined?(::PaperTrail)
@@ -7,7 +7,7 @@ module RailsAdmin
7
7
  class AuthorizationAdapter
8
8
  # This method is called first time only and used for setup
9
9
  def self.setup
10
- RailsAdmin::Extensions::ControllerExtension.include ::Pundit
10
+ RailsAdmin::Extensions::ControllerExtension.include defined?(::Pundit::Authorization) ? ::Pundit::Authorization : ::Pundit
11
11
  end
12
12
 
13
13
  # See the +authorize_with+ config method for where the initialization happens.
@@ -3,7 +3,7 @@ module RailsAdmin
3
3
  MAJOR = 3
4
4
  MINOR = 0
5
5
  PATCH = 0
6
- PRE = 'rc2'.freeze
6
+ PRE = nil
7
7
 
8
8
  class << self
9
9
  # @return [String]
@@ -14,6 +14,39 @@ module RailsAdmin
14
14
  def js
15
15
  JSON.parse(File.read("#{__dir__}/../../package.json"))['version']
16
16
  end
17
+
18
+ def actual_js_version
19
+ case RailsAdmin.config.asset_source
20
+ when :webpacker, :webpack
21
+ js_version_from_node_modules
22
+ else
23
+ js
24
+ end
25
+ end
26
+
27
+ def warn_with_js_version
28
+ return unless Rails.env.development? || Rails.env.test?
29
+
30
+ case actual_js_version
31
+ when js
32
+ # Good
33
+ when nil
34
+ warn "[Warning] Failed to detect RailsAdmin npm package, did you run 'yarn install'?"
35
+ else
36
+ warn <<~MSG
37
+ [Warning] RailsAdmin npm package version inconsistency detected, expected #{js} but actually used is #{actual_js_version}.
38
+ This may cause partial or total malfunction of RailsAdmin frontend features.
39
+ MSG
40
+ end
41
+ end
42
+
43
+ private
44
+
45
+ def js_version_from_node_modules
46
+ JSON.parse(File.read(Rails.root.join('node_modules/rails_admin/package.json')))['version']
47
+ rescue StandardError
48
+ nil
49
+ end
17
50
  end
18
51
  end
19
52
  end
data/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rails_admin",
3
- "version": "3.0.0-rc2",
3
+ "version": "3.0.0",
4
4
  "description": "RailsAdmin is a Rails engine that provides an easy-to-use interface for managing your data.",
5
5
  "homepage": "https://github.com/railsadminteam/rails_admin",
6
6
  "license": "MIT",
@@ -80,7 +80,7 @@ import I18n from "./i18n";
80
80
  .each(function () {
81
81
  $(this).siblings(".control-group").hide();
82
82
  });
83
- $(".form-actions .extra_buttons button")
83
+ $('button[name][type="submit"]')
84
84
  .attr("type", "button")
85
85
  .on("click", function () {
86
86
  var form = $(this).closest("form");
@@ -98,6 +98,10 @@ import I18n from "./i18n";
98
98
  $.each($("#filters_box").data("options"), function () {
99
99
  $.filters.append(this);
100
100
  });
101
+ // Workaround for https://github.com/heartcombo/devise/issues/5458
102
+ $("a[data-method]").on("click", function (event) {
103
+ window.Turbo.session.drive = false;
104
+ });
101
105
  });
102
106
 
103
107
  $(document).on("click", ".bulk-link", function (event) {
@@ -110,10 +114,15 @@ import I18n from "./i18n";
110
114
  event.preventDefault();
111
115
  $("#filters_box").html("");
112
116
  $("hr.filters_box").hide();
113
- $(this).parent().siblings("input[type='search']").val("");
117
+ $(this).siblings("input[type='search']").val("");
114
118
  $(this).parents("form").submit();
115
119
  });
116
120
 
121
+ $(document).on("click", "th.header", function (event) {
122
+ event.preventDefault();
123
+ window.Turbo.visit($(this).data("href"));
124
+ });
125
+
117
126
  $(document).on(
118
127
  "click",
119
128
  "#fields_to_export label input#check_all",