rails_admin 3.1.1 → 3.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +23 -17
  3. data/README.md +6 -4
  4. data/app/assets/javascripts/rails_admin/application.js.erb +3 -2
  5. data/app/assets/stylesheets/rails_admin/application.scss.erb +1 -1
  6. data/app/controllers/rails_admin/main_controller.rb +16 -1
  7. data/app/helpers/rails_admin/application_helper.rb +4 -0
  8. data/app/helpers/rails_admin/form_builder.rb +6 -5
  9. data/app/helpers/rails_admin/main_helper.rb +1 -1
  10. data/app/views/layouts/rails_admin/_head.html.erb +10 -7
  11. data/app/views/rails_admin/main/_form_boolean.html.erb +2 -2
  12. data/app/views/rails_admin/main/_form_filtering_multiselect.html.erb +5 -35
  13. data/app/views/rails_admin/main/_form_filtering_select.html.erb +6 -18
  14. data/app/views/rails_admin/main/_form_nested_many.html.erb +1 -1
  15. data/app/views/rails_admin/main/_form_nested_one.html.erb +1 -1
  16. data/app/views/rails_admin/main/_form_polymorphic_association.html.erb +12 -21
  17. data/app/views/rails_admin/main/delete.html.erb +1 -1
  18. data/app/views/rails_admin/main/index.html.erb +2 -2
  19. data/config/initializers/active_record_extensions.rb +0 -23
  20. data/lib/generators/rails_admin/importmap_formatter.rb +3 -2
  21. data/lib/generators/rails_admin/install_generator.rb +13 -1
  22. data/lib/generators/rails_admin/templates/rails_admin.vite.js +2 -0
  23. data/lib/rails_admin/abstract_model.rb +18 -7
  24. data/lib/rails_admin/adapters/active_record/association.rb +28 -11
  25. data/lib/rails_admin/adapters/active_record/object_extension.rb +0 -18
  26. data/lib/rails_admin/adapters/active_record.rb +56 -5
  27. data/lib/rails_admin/adapters/mongoid/association.rb +4 -4
  28. data/lib/rails_admin/adapters/mongoid/bson.rb +1 -0
  29. data/lib/rails_admin/adapters/mongoid/object_extension.rb +0 -5
  30. data/lib/rails_admin/adapters/mongoid.rb +13 -3
  31. data/lib/rails_admin/config/actions/export.rb +2 -1
  32. data/lib/rails_admin/config/actions/index.rb +7 -5
  33. data/lib/rails_admin/config/actions/show.rb +1 -1
  34. data/lib/rails_admin/config/configurable.rb +1 -1
  35. data/lib/rails_admin/config/fields/association.rb +41 -2
  36. data/lib/rails_admin/config/fields/base.rb +5 -5
  37. data/lib/rails_admin/config/fields/collection_association.rb +90 -0
  38. data/lib/rails_admin/config/fields/factories/active_storage.rb +2 -2
  39. data/lib/rails_admin/config/fields/factories/carrierwave.rb +1 -1
  40. data/lib/rails_admin/config/fields/factories/dragonfly.rb +1 -1
  41. data/lib/rails_admin/config/fields/factories/paperclip.rb +1 -1
  42. data/lib/rails_admin/config/fields/factories/shrine.rb +1 -1
  43. data/lib/rails_admin/config/fields/singular_association.rb +59 -0
  44. data/lib/rails_admin/config/fields/types/active_storage.rb +12 -7
  45. data/lib/rails_admin/config/fields/types/all.rb +0 -1
  46. data/lib/rails_admin/config/fields/types/belongs_to_association.rb +17 -20
  47. data/lib/rails_admin/config/fields/types/dragonfly.rb +0 -1
  48. data/lib/rails_admin/config/fields/types/file_upload.rb +7 -1
  49. data/lib/rails_admin/config/fields/types/has_and_belongs_to_many_association.rb +2 -2
  50. data/lib/rails_admin/config/fields/types/has_many_association.rb +2 -24
  51. data/lib/rails_admin/config/fields/types/has_one_association.rb +12 -22
  52. data/lib/rails_admin/config/fields/types/multiple_active_storage.rb +13 -8
  53. data/lib/rails_admin/config/fields/types/multiple_file_upload.rb +7 -1
  54. data/lib/rails_admin/config/fields/types/polymorphic_association.rb +32 -9
  55. data/lib/rails_admin/config/model.rb +3 -1
  56. data/lib/rails_admin/config.rb +9 -5
  57. data/lib/rails_admin/engine.rb +5 -0
  58. data/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +1 -1
  59. data/lib/rails_admin/extensions/pundit/authorization_adapter.rb +2 -1
  60. data/lib/rails_admin/extensions/url_for_extension.rb +15 -0
  61. data/lib/rails_admin/support/composite_keys_serializer.rb +15 -0
  62. data/lib/rails_admin/support/csv_converter.rb +0 -1
  63. data/lib/rails_admin/support/datetime.rb +1 -0
  64. data/lib/rails_admin/support/serialization_schema.rb +72 -0
  65. data/lib/rails_admin/version.rb +1 -1
  66. data/lib/rails_admin.rb +1 -0
  67. data/package.json +2 -2
  68. data/src/rails_admin/abstract-select.js +30 -0
  69. data/src/rails_admin/base.js +4 -1
  70. data/src/rails_admin/filtering-multiselect.js +2 -4
  71. data/src/rails_admin/filtering-select.js +2 -4
  72. data/src/rails_admin/ui.js +7 -1
  73. metadata +41 -18
  74. data/lib/rails_admin/adapters/composite_primary_keys/association.rb +0 -45
  75. data/lib/rails_admin/adapters/composite_primary_keys.rb +0 -40
  76. data/lib/rails_admin/config/fields/types/composite_keys_belongs_to_association.rb +0 -31
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 32f625ca21a5c94c2fc91766ae74ef690a92ff7f882068b70d617ad7b1e1ff3a
4
- data.tar.gz: ed3af9f17b3277f11a4b17db9beffe03d80294b453bb086d7aa819c46ce9cc1d
3
+ metadata.gz: a18178de7305b2be5286d22268d911c84952d779d46210548887cf220f5c052d
4
+ data.tar.gz: d0f6a162ca88c76b4be204608f5d265843c8bb59a55d93fe0b5fd65575e7c36e
5
5
  SHA512:
6
- metadata.gz: 2ad917ef318789585952a8e82084d3042960037a441ce1197f752f036e4f581107c37b0dab9466627fbe60e3f22e03d9a62f9af2f92ab9d77b1f5e02cfc85167
7
- data.tar.gz: 02225217c1f2997fccfce31605d494bdc5668778482ccb8c84231cf431efaafa4a830988526c1bfae88cac4a0342d41d1d7bd10b9507a8c60c2da2f1131d3250
6
+ metadata.gz: f93d7e8d4cab0ac54b62db959da642a0a83267234c92f7394cb2eb2ad44e821804fe7bd11a0a34eeb090eec10265dbe6abd06b0d3ce17c8992525976af513ba8
7
+ data.tar.gz: 2abe7c0eaca1c5ea064408bf389d7e108df43808e6551418c25945578e1d4d611a799a786b8de851b99ce86010f2615aa36a64b5d3b259c32f704f1b6ce627b9
data/Gemfile CHANGED
@@ -2,21 +2,15 @@
2
2
 
3
3
  source 'https://rubygems.org'
4
4
 
5
- gem 'appraisal', '>= 2.0'
6
- gem 'devise'
5
+ gem 'appraisal', '>= 2.0', require: false
6
+ gem 'devise', '~> 4.7'
7
7
  gem 'net-smtp', require: false
8
8
  gem 'rails'
9
+ gem 'sassc-rails', '~> 2.1'
10
+ gem 'turbo-rails'
11
+ gem 'vite_rails', require: false
9
12
  gem 'webpacker', require: false
10
- gem 'webrick', '~> 1.7'
11
-
12
- group :active_record do
13
- gem 'paper_trail'
14
-
15
- platforms :ruby, :mswin, :mingw, :x64_mingw do
16
- gem 'mysql2', '>= 0.3.14'
17
- gem 'sqlite3', '>= 1.3'
18
- end
19
- end
13
+ gem 'webrick'
20
14
 
21
15
  group :development, :test do
22
16
  gem 'pry', '>= 0.9'
@@ -24,22 +18,24 @@ end
24
18
 
25
19
  group :test do
26
20
  gem 'cancancan', '~> 3.0'
27
- gem 'carrierwave', ['>= 2.0.0.rc', '< 3']
28
- gem 'cuprite'
21
+ gem 'carrierwave', ['>= 2.2.1', '< 3']
22
+ gem 'cuprite', '!= 0.15.1'
29
23
  gem 'database_cleaner-active_record', '>= 2.0', require: false
30
- gem 'database_cleaner-mongoid', '>= 2.0', require: false
31
24
  gem 'dragonfly', '~> 1.0'
32
- gem 'factory_bot', '>= 4.2'
25
+ gem 'factory_bot', '>= 4.2', '!= 6.4.5'
33
26
  gem 'generator_spec', '>= 0.8'
27
+ gem 'json', '< 3' # Workaround for json 3.0 quirks_mode removal
28
+ gem 'kt-paperclip'
34
29
  gem 'launchy', '>= 2.2'
35
30
  gem 'mini_magick', '>= 3.4'
36
31
  gem 'pundit'
37
32
  gem 'rack-cache', require: 'rack/cache'
38
33
  gem 'rspec-expectations', '!= 3.8.3'
39
- gem 'rspec-rails', '>= 2.14'
34
+ gem 'rspec-rails', '>= 4.0.0.beta2'
40
35
  gem 'rspec-retry'
41
36
  gem 'rubocop', ['~> 1.20', '!= 1.22.2'], require: false
42
37
  gem 'rubocop-performance', require: false
38
+ gem 'shrine', '~> 3.0'
43
39
  gem 'simplecov', '>= 0.9', require: false
44
40
  gem 'simplecov-lcov', require: false
45
41
  gem 'timecop', '>= 0.5'
@@ -48,4 +44,14 @@ group :test do
48
44
  gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby]
49
45
  end
50
46
 
47
+ group :active_record do
48
+ gem 'paper_trail', '>= 12.0'
49
+
50
+ platforms :ruby, :mswin, :mingw, :x64_mingw do
51
+ gem 'mysql2', '>= 0.3.14'
52
+ gem 'pg', '>= 1.0.0'
53
+ gem 'sqlite3', '>= 1.3.0'
54
+ end
55
+ end
56
+
51
57
  gemspec
data/README.md CHANGED
@@ -1,13 +1,13 @@
1
1
  # RailsAdmin
2
2
 
3
3
  [![Gem Version](https://img.shields.io/gem/v/rails_admin.svg)][gem]
4
- [![Build Status](https://img.shields.io/github/workflow/status/railsadminteam/rails_admin/Test)][ghactions]
4
+ [![Build Status](https://github.com/railsadminteam/rails_admin/actions/workflows/test.yml/badge.svg)][ghactions]
5
5
  [![Coverage Status](https://img.shields.io/coveralls/railsadminteam/rails_admin.svg)][coveralls]
6
6
  [![Code Climate](https://codeclimate.com/github/railsadminteam/rails_admin.svg)][codeclimate]
7
7
  [![SemVer](https://api.dependabot.com/badges/compatibility_score?dependency-name=rails_admin&package-manager=bundler&version-scheme=semver)][semver]
8
8
 
9
9
  [gem]: https://rubygems.org/gems/rails_admin
10
- [ghactions]: https://github.com/railsadminteam/rails_admin/actions
10
+ [ghactions]: https://github.com/railsadminteam/rails_admin/actions/workflows/test.yml
11
11
  [coveralls]: https://coveralls.io/r/railsadminteam/rails_admin
12
12
  [codeclimate]: https://codeclimate.com/github/railsadminteam/rails_admin
13
13
  [semver]: https://dependabot.com/compatibility-score.html?dependency-name=rails_admin&package-manager=bundler&version-scheme=semver
@@ -19,8 +19,8 @@ RailsAdmin is a Rails engine that provides an easy-to-use interface for managing
19
19
  - Check out [the docs][docs].
20
20
  - Try the [live demo][demo]. ([Source code][dummy_app])
21
21
 
22
- [demo]: http://rails-admin-tb.herokuapp.com/
23
- [dummy_app]: https://github.com/bbenezech/dummy_app
22
+ [demo]: https://rails-admin.fly.dev/admin/
23
+ [dummy_app]: https://github.com/railsadminteam/rails_admin/tree/master/spec/dummy_app
24
24
  [docs]: https://github.com/railsadminteam/rails_admin/wiki
25
25
 
26
26
  ## Features
@@ -98,6 +98,8 @@ This library aims to support and is [tested against][ghactions] the following Ru
98
98
  - Ruby 2.6
99
99
  - Ruby 2.7
100
100
  - Ruby 3.0
101
+ - Ruby 3.1
102
+ - Ruby 3.2
101
103
  - [JRuby][]
102
104
 
103
105
  [jruby]: http://jruby.org/
@@ -9,6 +9,7 @@
9
9
  //= require 'rails_admin/popper'
10
10
  //= require 'rails_admin/bootstrap'
11
11
 
12
+ //= require 'rails_admin/abstract-select'
12
13
  //= require 'rails_admin/filter-box'
13
14
  //= require 'rails_admin/filtering-multiselect'
14
15
  //= require 'rails_admin/filtering-select'
@@ -20,10 +21,10 @@
20
21
  //= require 'rails_admin/ui'
21
22
  //= require 'rails_admin/custom/ui'
22
23
 
23
- <% if defined?(ActiveStorage) %>
24
+ <% if defined?(ActiveStorage::Engine) %>
24
25
  //= require activestorage
25
26
  <% end %>
26
- <% if defined?(ActionText) && Rails.gem_version >= Gem::Version.new('7.0') %>
27
+ <% if defined?(ActionText::Engine) && Rails.gem_version >= Gem::Version.new('7.0') %>
27
28
  //= require trix
28
29
  //= require actiontext
29
30
  <% end %>
@@ -30,6 +30,6 @@
30
30
  @import "rails_admin/styles/base/theming";
31
31
  @import "rails_admin/custom/theming";
32
32
 
33
- <% if defined?(ActionText) && Rails.gem_version >= Gem::Version.new('7.0') %>
33
+ <% if defined?(ActionText::Engine) && Rails.gem_version >= Gem::Version.new('7.0') %>
34
34
  @import "trix";
35
35
  <% end %>
@@ -56,7 +56,11 @@ module RailsAdmin
56
56
  end
57
57
 
58
58
  def back_or_index
59
- params[:return_to].presence && params[:return_to].include?(request.host) && (params[:return_to] != request.fullpath) ? params[:return_to] : index_path
59
+ allowed_return_to?(params[:return_to].to_s) ? params[:return_to] : index_path
60
+ end
61
+
62
+ def allowed_return_to?(url)
63
+ url != request.fullpath && url.start_with?(request.base_url, '/') && !url.start_with?('//')
60
64
  end
61
65
 
62
66
  def get_sort_hash(model_config)
@@ -90,6 +94,17 @@ module RailsAdmin
90
94
  model_config.send(action).with(controller: self, view: view_context, object: @object).visible_fields
91
95
  end
92
96
 
97
+ # Memoized, as export renders through index, which switches @action
98
+ def serialization_schema
99
+ @serialization_schema ||= begin
100
+ section = %i[export show].include?(@action.key) ? @model_config.send(@action.key) : @model_config.list
101
+ RailsAdmin::SerializationSchema.new(
102
+ section.with(controller: self, view: view_context, object: @object || @abstract_model.model.new),
103
+ include_associations: @action.key == :export,
104
+ )
105
+ end
106
+ end
107
+
93
108
  def sanitize_params_for!(action, model_config = @model_config, target_params = params[@abstract_model.param_key])
94
109
  return unless target_params.present?
95
110
 
@@ -7,6 +7,10 @@ module RailsAdmin
7
7
  action(action_name, abstract_model, object).try(:authorized?)
8
8
  end
9
9
 
10
+ def current_action
11
+ params[:action].in?(%w[create new]) ? 'create' : 'update'
12
+ end
13
+
10
14
  def current_action?(action, abstract_model = @abstract_model, object = @object)
11
15
  @action.custom_key == action.custom_key &&
12
16
  abstract_model.try(:to_param) == @abstract_model.try(:to_param) &&
@@ -108,8 +108,8 @@ module RailsAdmin
108
108
  end
109
109
 
110
110
  def hidden_field(method, options = {})
111
- if method == :id
112
- super method, {value: object.id.to_s}
111
+ if method == :id && object.id.is_a?(Array)
112
+ super method, {value: RailsAdmin.config.composite_keys_serializer.serialize(object.id)}
113
113
  else
114
114
  super
115
115
  end
@@ -149,9 +149,10 @@ module RailsAdmin
149
149
  private
150
150
 
151
151
  def nested_field_association?(field, nested_in)
152
- field.inverse_of.presence && nested_in.presence && field.inverse_of == nested_in.name &&
153
- (@template.instance_variable_get(:@model_config).abstract_model == field.abstract_model ||
154
- field.name == nested_in.inverse_of)
152
+ nested_in.presence &&
153
+ (field.name == nested_in.inverse_of ||
154
+ (field.inverse_of.presence && field.inverse_of == nested_in.name &&
155
+ @template.instance_variable_get(:@model_config).abstract_model == field.abstract_model))
155
156
  end
156
157
  end
157
158
  end
@@ -45,7 +45,7 @@ module RailsAdmin
45
45
  filter_for_field = duplet[1]
46
46
  filter_name = filter_for_field.keys.first
47
47
  filter_hash = filter_for_field.values.first
48
- unless (field = filterable_fields.find { |f| f.name == filter_name.to_sym })
48
+ unless (field = filterable_fields.find { |f| f.name == filter_name.to_sym }&.with({view: self}))
49
49
  raise "#{filter_name} is not currently filterable; filterable fields are #{filterable_fields.map(&:name).join(', ')}"
50
50
  end
51
51
 
@@ -1,7 +1,8 @@
1
- <meta content="IE=edge" http-equiv="X-UA-Compatible"/>
2
- <meta content="text/html; charset=utf-8" http-equiv="Content-Type"/>
3
- <meta content="width=device-width, initial-scale=1" name="viewport; charset=utf-8"/>
4
- <meta content="NONE,NOARCHIVE" name="robots"/>
1
+ <meta content="IE=edge" http-equiv="X-UA-Compatible">
2
+ <meta content="text/html; charset=utf-8" http-equiv="Content-Type">
3
+ <meta content="width=device-width, initial-scale=1" name="viewport; charset=utf-8">
4
+ <meta content="NONE,NOARCHIVE" name="robots">
5
+ <meta content="false" name="turbo-prefetch">
5
6
  <%= csrf_meta_tag %>
6
7
  <% case RailsAdmin::config.asset_source
7
8
  when :webpacker %>
@@ -12,6 +13,8 @@
12
13
  <%= stylesheet_link_tag "rails_admin/application.css", media: :all, data: {'turbo-track': 'reload'} %>
13
14
  <%= javascript_include_tag "rails_admin/application.js", defer: true, data: {'turbo-track': 'reload'} %>
14
15
  <% end %>
16
+ <% when :vite %>
17
+ <%= vite_javascript_tag "rails_admin", defer: true, data: {'turbo-track': 'reload'} %>
15
18
  <% when :webpack %>
16
19
  <%= stylesheet_link_tag "rails_admin.css", media: :all, data: {'turbo-track': 'reload'} %>
17
20
  <%= javascript_include_tag "rails_admin.js", defer: true, data: {'turbo-track': 'reload'} %>
@@ -19,11 +22,11 @@
19
22
  <%= stylesheet_link_tag "rails_admin.css", media: :all, data: {'turbo-track': 'reload'} %>
20
23
  <%= javascript_inline_importmap_tag(RailsAdmin::Engine.importmap.to_json(resolver: self)) %>
21
24
  <%= javascript_importmap_module_preload_tags(RailsAdmin::Engine.importmap) %>
22
- <%= javascript_importmap_shim_nonce_configuration_tag %>
23
- <%= javascript_importmap_shim_tag %>
25
+ <%= javascript_importmap_shim_nonce_configuration_tag if respond_to? :javascript_importmap_shim_nonce_configuration_tag %>
26
+ <%= javascript_importmap_shim_tag if respond_to? :javascript_importmap_shim_tag %>
24
27
  <%= # Preload jQuery and make it global, unless jQuery UI fails to initialize
25
28
  tag.script "import jQuery from 'jquery'; window.jQuery = jQuery;".html_safe, type: "module" %>
26
29
  <%= javascript_import_module_tag 'rails_admin' %>
27
30
  <% else
28
31
  raise "Unknown asset_source: #{RailsAdmin::config.asset_source}"
29
- end %>
32
+ end %>
@@ -2,9 +2,9 @@
2
2
  <div class="btn-group" role="group">
3
3
  <% {'1': [true, 'btn-outline-success'], '0': [false, 'btn-outline-danger'], '': [nil, 'btn-outline-secondary']}.each do |text, (value, btn_class)| %>
4
4
  <%= form.radio_button field.method_name, text, field.html_attributes.reverse_merge({ checked: field.form_value == value, required: field.required, class: 'btn-check' }) %>
5
- <label for="<%= form.object_name %>_<%= field.method_name %>_<%= text %>" class="<%= field.css_classes[value] %> btn <%= btn_class %>">
5
+ <%= form.label "#{field.method_name}_#{text}", class: "#{field.css_classes[value]} btn #{btn_class}" do %>
6
6
  <%= field.labels[value].html_safe %>
7
- </label>
7
+ <% end %>
8
8
  <% end %>
9
9
  </div>
10
10
  <% else %>
@@ -1,44 +1,14 @@
1
1
  <%
2
2
  config = field.associated_model_config
3
- source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
4
-
5
- selected = form.object.send(field.name)
6
- selected_ids = selected.map{|s| s.send(field.associated_primary_key).to_s}
7
-
8
- current_action = params[:action].in?(['create', 'new']) ? 'create' : 'update'
9
-
10
- xhr = !field.associated_collection_cache_all
11
-
12
- collection = if xhr
13
- selected.map { |o| [o.send(field.associated_object_label_method), o.send(field.associated_primary_key)] }
14
- else
15
- i = 0
16
- controller.list_entries(config, :index, field.associated_collection_scope, false).map { |o| [o.send(field.associated_object_label_method), o.send(field.associated_primary_key).to_s] }.sort_by {|a| [selected_ids.index(a[1]) || selected_ids.size, i+=1] }
17
- end
18
-
19
- js_data = {
20
- xhr: xhr,
21
- :'edit-url' => (field.inline_edit && authorized?(:edit, config.abstract_model) ? edit_path(model_name: config.abstract_model.to_param, id: '__ID__') : ''),
22
- remote_source: index_path(config.abstract_model, source_object_id: form.object.id, source_abstract_model: source_abstract_model.to_param, associated_collection: field.name, current_action: current_action, compact: true),
23
- sortable: !!field.orderable,
24
- removable: !!field.removable,
25
- cacheAll: !!field.associated_collection_cache_all,
26
- regional: {
27
- add: t('admin.misc.add_new'),
28
- chooseAll: t('admin.misc.chose_all'),
29
- clearAll: t('admin.misc.clear_all'),
30
- down: t('admin.misc.down'),
31
- remove: t('admin.misc.remove'),
32
- search: t('admin.misc.search'),
33
- up: t('admin.misc.up')
34
- }
35
- }
36
3
  %>
4
+
37
5
  <div class="row">
38
6
  <div class="col-auto">
39
7
  <input name="<%= form.dom_name(field) %>" type="hidden" />
40
- <% selected_ids = (hdv = field.form_default_value).nil? ? selected_ids : hdv %>
41
- <%= form.select field.method_name, collection, { selected: selected_ids, object: form.object }, field.html_attributes.reverse_merge({data: { filteringmultiselect: true, options: js_data.to_json }, multiple: true}) %>
8
+ <%=
9
+ form.select field.method_name, field.collection, { selected: field.form_value, object: form.object },
10
+ field.html_attributes.reverse_merge({data: { filteringmultiselect: true, options: field.widget_options.to_json }, multiple: true})
11
+ %>
42
12
  </div>
43
13
  <% if authorized?(:new, config.abstract_model) && field.inline_add %>
44
14
  <div class="col-sm-4 modal-actions">
@@ -1,33 +1,21 @@
1
1
  <%
2
2
  config = field.associated_model_config
3
- source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
4
-
5
- current_action = params[:action].in?(['create', 'new']) ? 'create' : 'update'
6
-
7
- edit_url = authorized?(:edit, config.abstract_model) ? edit_path(model_name: config.abstract_model.to_param, modal: true, id: '__ID__') : ''
8
-
9
- xhr = !field.associated_collection_cache_all
10
-
11
- collection = xhr ? [[field.formatted_value, field.selected_id]] : controller.list_entries(config, :index, field.associated_collection_scope, false).map { |o| [o.send(field.associated_object_label_method), o.send(field.associated_primary_key).to_s] }
12
-
13
- js_data = {
14
- xhr: xhr,
15
- remote_source: index_path(config.abstract_model.to_param, source_object_id: form.object.id, source_abstract_model: source_abstract_model.to_param, associated_collection: field.name, current_action: current_action, compact: true)
16
- }
17
3
  %>
18
4
 
19
5
  <div class="row">
20
6
  <div class="col-sm-4">
21
- <% selected_id = (hdv = field.form_default_value).nil? ? field.selected_id : hdv %>
22
- <%= 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') }) %>
7
+ <%=
8
+ form.select field.method_name, field.collection, { selected: field.form_value, include_blank: true },
9
+ field.html_attributes.reverse_merge({ data: { filteringselect: true, options: field.widget_options.to_json }, placeholder: t('admin.misc.search') })
10
+ %>
23
11
  </div>
24
12
  <div class="col-sm-8 mt-2 mt-md-0 modal-actions">
25
13
  <% if authorized?(:new, config.abstract_model) && field.inline_add %>
26
14
  <% path_hash = { model_name: config.abstract_model.to_param, modal: true }.merge!(field.associated_prepopulate_params) %>
27
15
  <%= link_to "<i class=\"fas fa-plus\"></i> ".html_safe + wording_for(:link, :new, config.abstract_model), '#', data: { link: new_path(path_hash) }, class: "btn btn-info create" %>
28
16
  <% end %>
29
- <% if edit_url.present? && field.inline_edit %>
30
- <%= link_to "<i class=\"fas fa-pencil-alt\"></i> ".html_safe + wording_for(:link, :edit, config.abstract_model), '#', data: { link: edit_url }, class: "btn btn-info update ms-2#{' disabled' if field.value.nil?}" %>
17
+ <% if authorized?(:edit, config.abstract_model) && field.inline_edit %>
18
+ <%= link_to "<i class=\"fas fa-pencil-alt\"></i> ".html_safe + wording_for(:link, :edit, config.abstract_model), '#', data: { link: edit_path(model_name: config.abstract_model.to_param, modal: true, id: '__ID__') }, class: "btn btn-info update ms-2#{' disabled' if field.value.nil?}" %>
31
19
  <% end %>
32
20
  </div>
33
21
  </div>
@@ -3,7 +3,7 @@
3
3
  <a class="<%= (field.active? ? 'active' : '') %> btn btn-info toggler" data-bs-target="<%= form.jquery_namespace(field) %> .collapse" data-bs-toggle="collapse" role="button">
4
4
  <i class="fas"></i>
5
5
  </a>
6
- <% unless field.nested_form[:update_only] || !field.inline_add %>
6
+ <% if field.inline_add %>
7
7
  <%= form.link_to_add "<i class=\"fas fa-plus\"></i> #{wording_for(:link, :new, field.associated_model_config.abstract_model)}".html_safe, field.name, { class: 'btn btn-info' } %>
8
8
  <% end %>
9
9
  </div>
@@ -4,7 +4,7 @@
4
4
  <a class="<%= (field.active? ? 'active' : '') %> btn btn-info toggler" data-bs-target="<%= form.jquery_namespace(field) %> .collapse" data-bs-toggle="collapse" role="button">
5
5
  <i class="fas"></i>
6
6
  </a>
7
- <% unless field.nested_form[:update_only] || !field.inline_add %>
7
+ <% if field.inline_add %>
8
8
  <%= form.link_to_add "<i class=\"fas fa-plus\"></i> #{wording_for(:link, :new, field.associated_model_config.abstract_model)}".html_safe, field.name, { class: 'btn btn-info', :'data-add-label' => "<i class=\"fas fa-plus\"></i> #{wording_for(:link, :new, field.associated_model_config.abstract_model)}".gsub("\n", "") } %>
9
9
  <% end %>
10
10
  </div>
@@ -1,32 +1,23 @@
1
1
  <%
2
- type_collection = field.polymorphic_type_collection
3
- type_column = field.association.foreign_type.to_s
4
- selected_type = field.bindings[:object].send(type_column)
5
- selected = field.bindings[:object].send(field.association.name)
6
- collection = selected ? [[field.formatted_value, selected.id]] : [[]]
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
- source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
14
- options.merge(model.second.downcase.gsub('::', '-') => {
15
- xhr: true,
16
- remote_source: index_path(model.second.underscore, source_object_id: form.object.id, source_abstract_model: source_abstract_model.to_param, current_action: current_action, compact: true),
17
- float_left: false
18
- })
19
- end
2
+ column_type_dom_id = form.dom_id(field).sub(field.method_name.to_s, field.type_column)
20
3
  %>
21
4
 
22
5
  <div class="row">
23
6
  <div class="col-sm-3">
24
- <% js_data.each do |model, value| %>
7
+ <% field.widget_options_for_types.each do |model, value| %>
25
8
  <div data-options="<%= value.to_json %>" id="<%= model %>-js-options"></div>
26
9
  <% end %>
27
- <%= form.select type_column, type_collection, {include_blank: true, selected: selected_type}, class: "form-select", id: column_type_dom_id, data: { polymorphic: true, urls: field.polymorphic_type_urls.to_json }, style: "float: left; margin-right: 10px;" %>
10
+ <%=
11
+ form.select field.type_column, field.type_collection, {include_blank: true, selected: field.selected_type},
12
+ class: "form-select", id: column_type_dom_id, data: { polymorphic: true, urls: field.type_urls.to_json },
13
+ style: "float: left; margin-right: 10px;"
14
+ %>
28
15
  </div>
29
16
  <div class="col-sm-4">
30
- <%= 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' %>
17
+ <%=
18
+ form.select field.method_name, field.collection, {include_blank: true, selected: field.selected_id},
19
+ class: "form-control", data: { filteringselect: true, options: field.widget_options },
20
+ placeholder: 'Search'
21
+ %>
31
22
  </div>
32
23
  </div>
@@ -1,6 +1,6 @@
1
1
  <h4>
2
2
  <%= t("admin.form.are_you_sure_you_want_to_delete_the_object", model_name: @abstract_model.pretty_name.downcase) %>
3
- &ldquo;<strong><%= @model_config.with(object: @object).object_label %></strong>&rdquo;
3
+ <q><strong><%= @model_config.with(object: @object).object_label %></strong></q>
4
4
  <%= t("admin.form.all_of_the_following_related_items_will_be_deleted") %>
5
5
  </h4>
6
6
  <ul>
@@ -133,9 +133,9 @@
133
133
  <% end %>
134
134
  <% properties.map{ |property| property.bind(:object, object) }.each do |property| %>
135
135
  <% value = property.pretty_value %>
136
- <td class="<%= [property.sticky? && 'sticky', property.css_class, property.type_css_class].select(&:present?).join(' ') %>" title="<%= strip_tags(value.to_s) %>">
136
+ <%= content_tag(:td, class: [property.sticky? && 'sticky', property.css_class, property.type_css_class].select(&:present?), title: strip_tags(value.to_s)) do %>
137
137
  <%= value %>
138
- </td>
138
+ <% end %>
139
139
  <% end %>
140
140
  <td class="last links ra-sidescroll-frozen">
141
141
  <ul class="nav d-inline list-inline">
@@ -20,27 +20,4 @@ ActiveSupport.on_load(:active_record) do
20
20
  end
21
21
  end
22
22
  end
23
-
24
- if defined?(CompositePrimaryKeys)
25
- # Apply patch until the fix is released:
26
- # https://github.com/composite-primary-keys/composite_primary_keys/pull/572
27
- CompositePrimaryKeys::CompositeKeys.class_eval do
28
- alias_method :to_param, :to_s
29
- end
30
-
31
- CompositePrimaryKeys::CollectionAssociation.prepend(Module.new do
32
- def ids_writer(ids)
33
- if reflection.association_primary_key.is_a? Array
34
- ids = CompositePrimaryKeys.normalize(Array(ids).reject(&:blank?), reflection.association_primary_key.size)
35
- reflection.association_primary_key.each_with_index do |primary_key, i|
36
- pk_type = klass.type_for_attribute(primary_key)
37
- ids.each do |id|
38
- id[i] = pk_type.cast(id[i]) if id.is_a? Array
39
- end
40
- end
41
- end
42
- super ids
43
- end
44
- end)
45
- end
46
23
  end
@@ -6,12 +6,13 @@ module RailsAdmin
6
6
  class ImportmapFormatter
7
7
  attr_reader :packager
8
8
 
9
- def initialize(path = 'confing/importmap.rails_admin.rb')
9
+ def initialize(path = 'config/importmap.rails_admin.rb')
10
10
  @packager = Importmap::Packager.new(path)
11
11
  end
12
12
 
13
13
  def format
14
- imports = packager.import("rails_admin@#{RailsAdmin::Version.js}")
14
+ imports = packager.import("rails_admin@#{RailsAdmin::Version.js}", from: 'jspm.io')
15
+ imports = imports[:imports] if imports.key?(:imports)
15
16
 
16
17
  # Use ESM compatible version to work around https://github.com/cljsjs/packages/issues/1579
17
18
  imports['@popperjs/core'].gsub!('lib/index.js', 'dist/esm/popper.js')
@@ -10,7 +10,7 @@ module RailsAdmin
10
10
  include Generators::Utils::InstanceMethods
11
11
 
12
12
  argument :_namespace, type: :string, required: false, desc: 'RailsAdmin url namespace'
13
- class_option :asset, type: :string, required: false, default: nil, desc: 'Asset delivery method [options: webpacker, webpack, sprockets, importmap]'
13
+ class_option :asset, type: :string, required: false, default: nil, desc: 'Asset delivery method [options: webpacker, webpack, sprockets, importmap, vite]'
14
14
  desc 'RailsAdmin installation generator'
15
15
 
16
16
  def install
@@ -33,6 +33,8 @@ module RailsAdmin
33
33
  configure_for_importmap
34
34
  when 'webpacker'
35
35
  configure_for_webpacker5
36
+ when 'vite'
37
+ configure_for_vite
36
38
  when 'sprockets'
37
39
  configure_for_sprockets
38
40
  else
@@ -51,6 +53,8 @@ module RailsAdmin
51
53
  'webpack'
52
54
  elsif Rails.root.join('config/importmap.rb').exist?
53
55
  'importmap'
56
+ elsif defined?(ViteRuby)
57
+ 'vite'
54
58
  else
55
59
  'sprockets'
56
60
  end
@@ -68,6 +72,14 @@ module RailsAdmin
68
72
  add_package_json_field('resolutions', {'rails_admin/@fortawesome/fontawesome-free' => '^5.15.0'})
69
73
  end
70
74
 
75
+ def configure_for_vite
76
+ vite_source_code_dir = ViteRuby.config.source_code_dir
77
+ run "yarn add rails_admin@#{RailsAdmin::Version.js} sass"
78
+ template('rails_admin.vite.js', File.join(vite_source_code_dir, 'entrypoints', 'rails_admin.js'))
79
+ @fa_font_path = '@fortawesome/fontawesome-free/webfonts'
80
+ template('rails_admin.scss.erb', File.join(vite_source_code_dir, 'stylesheets', 'rails_admin.scss'))
81
+ end
82
+
71
83
  def configure_for_webpack
72
84
  run "yarn add rails_admin@#{RailsAdmin::Version.js}"
73
85
  template 'rails_admin.js', 'app/javascript/rails_admin.js'
@@ -0,0 +1,2 @@
1
+ import "~/stylesheets/rails_admin.scss";
2
+ import "rails_admin/src/rails_admin/base";
@@ -60,6 +60,14 @@ module RailsAdmin
60
60
  @model_name.constantize
61
61
  end
62
62
 
63
+ def quoted_table_name
64
+ table_name
65
+ end
66
+
67
+ def quote_column_name(name)
68
+ name
69
+ end
70
+
63
71
  def to_s
64
72
  model.to_s
65
73
  end
@@ -97,17 +105,20 @@ module RailsAdmin
97
105
  end
98
106
  end
99
107
 
108
+ def format_id(id)
109
+ id
110
+ end
111
+
112
+ def parse_id(id)
113
+ id
114
+ end
115
+
100
116
  private
101
117
 
102
118
  def initialize_active_record
103
119
  @adapter = :active_record
104
- if defined?(::CompositePrimaryKeys)
105
- require 'rails_admin/adapters/composite_primary_keys'
106
- extend Adapters::CompositePrimaryKeys
107
- else
108
- require 'rails_admin/adapters/active_record'
109
- extend Adapters::ActiveRecord
110
- end
120
+ require 'rails_admin/adapters/active_record'
121
+ extend Adapters::ActiveRecord
111
122
  end
112
123
 
113
124
  def initialize_mongoid