rails_admin 3.0.0 → 3.1.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.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -0
  3. data/Rakefile +2 -0
  4. data/app/assets/javascripts/rails_admin/{application.js → application.js.erb} +8 -0
  5. data/app/assets/stylesheets/rails_admin/{application.scss → application.scss.erb} +4 -0
  6. data/app/controllers/rails_admin/application_controller.rb +2 -0
  7. data/app/controllers/rails_admin/main_controller.rb +9 -14
  8. data/app/helpers/rails_admin/application_helper.rb +37 -9
  9. data/app/helpers/rails_admin/form_builder.rb +10 -0
  10. data/app/helpers/rails_admin/main_helper.rb +7 -15
  11. data/app/views/layouts/rails_admin/_head.html.erb +12 -3
  12. data/app/views/layouts/rails_admin/_secondary_navigation.html.erb +3 -1
  13. data/app/views/layouts/rails_admin/_sidebar_navigation.html.erb +1 -1
  14. data/app/views/layouts/rails_admin/application.html.erb +4 -1
  15. data/app/views/rails_admin/main/_dashboard_history.html.erb +1 -1
  16. data/app/views/rails_admin/main/_form_action_text.html.erb +2 -1
  17. data/app/views/rails_admin/main/_form_file_upload.html.erb +1 -1
  18. data/app/views/rails_admin/main/_form_filtering_multiselect.html.erb +2 -2
  19. data/app/views/rails_admin/main/_form_filtering_select.html.erb +1 -1
  20. data/app/views/rails_admin/main/_form_multiple_file_upload.html.erb +1 -1
  21. data/app/views/rails_admin/main/dashboard.html.erb +2 -2
  22. data/app/views/rails_admin/main/history.html.erb +1 -1
  23. data/app/views/rails_admin/main/index.html.erb +7 -19
  24. data/config/initializers/active_record_extensions.rb +26 -3
  25. data/config/initializers/mongoid_extensions.rb +2 -0
  26. data/config/locales/rails_admin.en.yml +3 -2
  27. data/config/routes.rb +2 -0
  28. data/lib/generators/rails_admin/importmap_formatter.rb +28 -0
  29. data/lib/generators/rails_admin/install_generator.rb +68 -9
  30. data/lib/generators/rails_admin/templates/rails_admin.js +1 -0
  31. data/lib/generators/rails_admin/templates/rails_admin.scss.erb +1 -0
  32. data/lib/generators/rails_admin/templates/rails_admin.webpacker.js +2 -0
  33. data/lib/generators/rails_admin/utils.rb +2 -0
  34. data/lib/rails_admin/abstract_model.rb +9 -2
  35. data/lib/rails_admin/adapters/active_record/association.rb +11 -1
  36. data/lib/rails_admin/adapters/active_record/object_extension.rb +2 -0
  37. data/lib/rails_admin/adapters/active_record/property.rb +2 -0
  38. data/lib/rails_admin/adapters/active_record.rb +25 -2
  39. data/lib/rails_admin/adapters/composite_primary_keys/association.rb +45 -0
  40. data/lib/rails_admin/adapters/composite_primary_keys.rb +40 -0
  41. data/lib/rails_admin/adapters/mongoid/association.rb +14 -4
  42. data/lib/rails_admin/adapters/mongoid/bson.rb +2 -0
  43. data/lib/rails_admin/adapters/mongoid/extension.rb +3 -3
  44. data/lib/rails_admin/adapters/mongoid/object_extension.rb +2 -0
  45. data/lib/rails_admin/adapters/mongoid/property.rb +2 -0
  46. data/lib/rails_admin/adapters/mongoid.rb +4 -2
  47. data/lib/rails_admin/config/actions/base.rb +2 -0
  48. data/lib/rails_admin/config/actions/bulk_delete.rb +2 -0
  49. data/lib/rails_admin/config/actions/dashboard.rb +2 -0
  50. data/lib/rails_admin/config/actions/delete.rb +2 -0
  51. data/lib/rails_admin/config/actions/edit.rb +2 -0
  52. data/lib/rails_admin/config/actions/export.rb +2 -0
  53. data/lib/rails_admin/config/actions/history_index.rb +2 -0
  54. data/lib/rails_admin/config/actions/history_show.rb +2 -0
  55. data/lib/rails_admin/config/actions/index.rb +2 -0
  56. data/lib/rails_admin/config/actions/new.rb +2 -0
  57. data/lib/rails_admin/config/actions/show.rb +2 -0
  58. data/lib/rails_admin/config/actions/show_in_app.rb +2 -0
  59. data/lib/rails_admin/config/actions.rb +2 -0
  60. data/lib/rails_admin/config/configurable.rb +2 -0
  61. data/lib/rails_admin/config/const_load_suppressor.rb +78 -0
  62. data/lib/rails_admin/config/fields/association.rb +2 -0
  63. data/lib/rails_admin/config/fields/base.rb +44 -14
  64. data/lib/rails_admin/config/fields/factories/action_text.rb +2 -0
  65. data/lib/rails_admin/config/fields/factories/active_storage.rb +2 -0
  66. data/lib/rails_admin/config/fields/factories/association.rb +6 -5
  67. data/lib/rails_admin/config/fields/factories/carrierwave.rb +2 -0
  68. data/lib/rails_admin/config/fields/factories/devise.rb +2 -0
  69. data/lib/rails_admin/config/fields/factories/dragonfly.rb +2 -0
  70. data/lib/rails_admin/config/fields/factories/enum.rb +2 -0
  71. data/lib/rails_admin/config/fields/factories/paperclip.rb +2 -0
  72. data/lib/rails_admin/config/fields/factories/password.rb +2 -0
  73. data/lib/rails_admin/config/fields/factories/shrine.rb +2 -0
  74. data/lib/rails_admin/config/fields/group.rb +2 -0
  75. data/lib/rails_admin/config/fields/types/action_text.rb +6 -0
  76. data/lib/rails_admin/config/fields/types/active_record_enum.rb +2 -0
  77. data/lib/rails_admin/config/fields/types/active_storage.rb +14 -0
  78. data/lib/rails_admin/config/fields/types/all.rb +3 -0
  79. data/lib/rails_admin/config/fields/types/belongs_to_association.rb +7 -5
  80. data/lib/rails_admin/config/fields/types/boolean.rb +7 -1
  81. data/lib/rails_admin/config/fields/types/bson_object_id.rb +2 -0
  82. data/lib/rails_admin/config/fields/types/carrierwave.rb +2 -0
  83. data/lib/rails_admin/config/fields/types/citext.rb +2 -0
  84. data/lib/rails_admin/config/fields/types/ck_editor.rb +2 -0
  85. data/lib/rails_admin/config/fields/types/code_mirror.rb +2 -0
  86. data/lib/rails_admin/config/fields/types/color.rb +2 -0
  87. data/lib/rails_admin/config/fields/types/composite_keys_belongs_to_association.rb +31 -0
  88. data/lib/rails_admin/config/fields/types/date.rb +2 -0
  89. data/lib/rails_admin/config/fields/types/datetime.rb +12 -0
  90. data/lib/rails_admin/config/fields/types/decimal.rb +2 -0
  91. data/lib/rails_admin/config/fields/types/dragonfly.rb +2 -0
  92. data/lib/rails_admin/config/fields/types/enum.rb +15 -2
  93. data/lib/rails_admin/config/fields/types/file_upload.rb +2 -0
  94. data/lib/rails_admin/config/fields/types/float.rb +2 -0
  95. data/lib/rails_admin/config/fields/types/froala.rb +2 -0
  96. data/lib/rails_admin/config/fields/types/has_and_belongs_to_many_association.rb +2 -0
  97. data/lib/rails_admin/config/fields/types/has_many_association.rb +2 -0
  98. data/lib/rails_admin/config/fields/types/has_one_association.rb +7 -1
  99. data/lib/rails_admin/config/fields/types/hidden.rb +2 -0
  100. data/lib/rails_admin/config/fields/types/inet.rb +2 -0
  101. data/lib/rails_admin/config/fields/types/integer.rb +2 -0
  102. data/lib/rails_admin/config/fields/types/json.rb +2 -0
  103. data/lib/rails_admin/config/fields/types/multiple_active_storage.rb +22 -0
  104. data/lib/rails_admin/config/fields/types/multiple_carrierwave.rb +2 -0
  105. data/lib/rails_admin/config/fields/types/multiple_file_upload.rb +2 -0
  106. data/lib/rails_admin/config/fields/types/numeric.rb +6 -0
  107. data/lib/rails_admin/config/fields/types/paperclip.rb +2 -0
  108. data/lib/rails_admin/config/fields/types/password.rb +2 -0
  109. data/lib/rails_admin/config/fields/types/polymorphic_association.rb +2 -0
  110. data/lib/rails_admin/config/fields/types/serialized.rb +2 -0
  111. data/lib/rails_admin/config/fields/types/shrine.rb +2 -0
  112. data/lib/rails_admin/config/fields/types/simple_mde.rb +2 -0
  113. data/lib/rails_admin/config/fields/types/string.rb +2 -0
  114. data/lib/rails_admin/config/fields/types/string_like.rb +6 -0
  115. data/lib/rails_admin/config/fields/types/text.rb +2 -0
  116. data/lib/rails_admin/config/fields/types/time.rb +6 -0
  117. data/lib/rails_admin/config/fields/types/timestamp.rb +2 -0
  118. data/lib/rails_admin/config/fields/types/uuid.rb +2 -0
  119. data/lib/rails_admin/config/fields/types/wysihtml5.rb +2 -0
  120. data/lib/rails_admin/config/fields/types.rb +2 -0
  121. data/lib/rails_admin/config/fields.rb +3 -1
  122. data/lib/rails_admin/config/groupable.rb +2 -0
  123. data/lib/rails_admin/config/has_description.rb +2 -0
  124. data/lib/rails_admin/config/has_fields.rb +3 -1
  125. data/lib/rails_admin/config/has_groups.rb +2 -0
  126. data/lib/rails_admin/config/hideable.rb +2 -0
  127. data/lib/rails_admin/config/inspectable.rb +2 -0
  128. data/lib/rails_admin/config/lazy_model.rb +74 -0
  129. data/lib/rails_admin/config/model.rb +5 -1
  130. data/lib/rails_admin/config/proxyable/proxy.rb +2 -0
  131. data/lib/rails_admin/config/proxyable.rb +2 -0
  132. data/lib/rails_admin/config/sections/base.rb +2 -0
  133. data/lib/rails_admin/config/sections/create.rb +2 -0
  134. data/lib/rails_admin/config/sections/edit.rb +2 -0
  135. data/lib/rails_admin/config/sections/export.rb +2 -0
  136. data/lib/rails_admin/config/sections/list.rb +6 -0
  137. data/lib/rails_admin/config/sections/modal.rb +2 -0
  138. data/lib/rails_admin/config/sections/nested.rb +2 -0
  139. data/lib/rails_admin/config/sections/show.rb +2 -0
  140. data/lib/rails_admin/config/sections/update.rb +2 -0
  141. data/lib/rails_admin/config/sections.rb +2 -0
  142. data/lib/rails_admin/config.rb +26 -37
  143. data/lib/rails_admin/engine.rb +19 -17
  144. data/lib/rails_admin/extension.rb +2 -0
  145. data/lib/rails_admin/extensions/cancancan/authorization_adapter.rb +21 -4
  146. data/lib/rails_admin/extensions/cancancan.rb +2 -0
  147. data/lib/rails_admin/extensions/controller_extension.rb +2 -0
  148. data/lib/rails_admin/extensions/paper_trail/auditing_adapter.rb +49 -27
  149. data/lib/rails_admin/extensions/paper_trail.rb +2 -0
  150. data/lib/rails_admin/extensions/pundit/authorization_adapter.rb +2 -0
  151. data/lib/rails_admin/extensions/pundit.rb +2 -0
  152. data/lib/rails_admin/support/csv_converter.rb +2 -1
  153. data/lib/rails_admin/support/datetime.rb +3 -1
  154. data/lib/rails_admin/support/es_module_processor.rb +23 -0
  155. data/lib/rails_admin/support/hash_helper.rb +2 -0
  156. data/lib/rails_admin/version.rb +3 -1
  157. data/lib/rails_admin.rb +7 -2
  158. data/lib/tasks/rails_admin.rake +2 -0
  159. data/package.json +2 -2
  160. data/src/rails_admin/base.js +13 -1
  161. data/src/rails_admin/filter-box.js +165 -209
  162. data/src/rails_admin/filtering-multiselect.js +5 -10
  163. data/src/rails_admin/filtering-select.js +16 -7
  164. data/src/rails_admin/i18n.js +3 -1
  165. data/src/rails_admin/nested-form-hooks.js +6 -4
  166. data/src/rails_admin/remote-form.js +5 -5
  167. data/src/rails_admin/styles/base/theming.scss +25 -8
  168. data/src/rails_admin/styles/base.scss +5 -5
  169. data/src/rails_admin/styles/widgets.scss +1 -1
  170. data/src/rails_admin/ui.js +45 -18
  171. data/src/rails_admin/widgets.js +7 -2
  172. data/vendor/assets/fonts/rails_admin/fa-solid-900.ttf +0 -0
  173. data/vendor/assets/fonts/rails_admin/fa-solid-900.woff2 +0 -0
  174. data/vendor/assets/javascripts/rails_admin/jquery3.js +118 -109
  175. data/vendor/assets/stylesheets/rails_admin/font-awesome.scss +4531 -2782
  176. metadata +15 -12
  177. data/lib/generators/rails_admin/templates/rails_admin.js.erb +0 -2
  178. data/lib/generators/rails_admin/templates/rails_admin.scss +0 -1
  179. data/lib/generators/rails_admin/templates/webpack.config.js +0 -29
  180. data/lib/rails_admin/support/esmodule_preprocessor.rb +0 -33
  181. data/vendor/assets/fonts/rails_admin/fa-solid-900.eot +0 -0
  182. data/vendor/assets/fonts/rails_admin/fa-solid-900.svg +0 -5034
  183. data/vendor/assets/fonts/rails_admin/fa-solid-900.woff +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a20d0a9cc9b7702c63e5e92918ac89f986b2d3d1e666539fd0c16562508bdf85
4
- data.tar.gz: 7d5784f25b6a16c0d2a05b827a8bc9990da28d056d34b2569ea628910088ae89
3
+ metadata.gz: 4703829ff74c1be721a1622986bfe87c98c07e908991e997c903070c12216255
4
+ data.tar.gz: 3eddba360a94a4bd0a3d3e0c1eb62af9752b90e4637082b3ce6e3d576274c7b8
5
5
  SHA512:
6
- metadata.gz: ea7b4265126ff76473d461cd0630feb1a4e3ad71476d2843577a25fdaea53fed0ca57b06b55dbe63615f5004151796b346f9bca2492ff71175d44faffbe24c38
7
- data.tar.gz: 58fb832bd8e1e7c124e79eabd01393da73217714e0b52a32ea215ef1e1b2d4f33390928ed15686eeed983446d74a914ac947cd709bd67180799bf8bd9017bc4a
6
+ metadata.gz: b13e1468096711b8dfc4217563f26524512e2e219cdf69bf56aece88400bce7a3b2ec958fc1676f1fd253745c86ca1739f35f0e199983e0597fce986cda41484
7
+ data.tar.gz: bdb5a417cd53c3e301358ce96452b3d96acc73ccdd752a81187429aaabaa969c7c77fa02ee72be201c8303e61a3f6ffc3f07aea77ac1fb3a8d70da717c117647
data/Gemfile CHANGED
@@ -1,7 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  gem 'appraisal', '>= 2.0'
4
6
  gem 'devise'
7
+ gem 'net-smtp', require: false
5
8
  gem 'rails'
6
9
  gem 'webpacker', require: false
7
10
  gem 'webrick', '~> 1.7'
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Add your own tasks in files placed in lib/tasks ending in .rake,
2
4
  # for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
3
5
 
@@ -19,3 +19,11 @@
19
19
  //= require 'rails_admin/sidescroll'
20
20
  //= require 'rails_admin/ui'
21
21
  //= require 'rails_admin/custom/ui'
22
+
23
+ <% if defined?(ActiveStorage) %>
24
+ //= require activestorage
25
+ <% end %>
26
+ <% if defined?(ActionText) && Rails.gem_version >= Gem::Version.new('7.0') %>
27
+ //= require trix
28
+ //= require actiontext
29
+ <% end %>
@@ -29,3 +29,7 @@
29
29
 
30
30
  @import "rails_admin/styles/base/theming";
31
31
  @import "rails_admin/custom/theming";
32
+
33
+ <% if defined?(ActionText) && Rails.gem_version >= Gem::Version.new('7.0') %>
34
+ @import "trix";
35
+ <% end %>
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rails_admin/abstract_model'
2
4
 
3
5
  module RailsAdmin
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RailsAdmin
2
4
  class MainController < RailsAdmin::ApplicationController
3
5
  include ActionView::Helpers::TextHelper
@@ -58,23 +60,15 @@ module RailsAdmin
58
60
  end
59
61
 
60
62
  def get_sort_hash(model_config)
61
- abstract_model = model_config.abstract_model
62
63
  field = model_config.list.fields.detect { |f| f.name.to_s == params[:sort] }
64
+ # If no sort param, default to the `sort_by` specified in the list config
65
+ field ||= model_config.list.possible_fields.detect { |f| f.name == model_config.list.sort_by.try(:to_sym) }
63
66
 
64
67
  column =
65
68
  if field.nil? || field.sortable == false # use default sort, asked field does not exist or is not sortable
66
- field = model_config.list.possible_fields.detect { |f| f.name == model_config.list.sort_by.to_sym }
67
- "#{abstract_model.table_name}.#{model_config.list.sort_by}"
68
- elsif field.sortable == true # use the given field
69
- "#{abstract_model.table_name}.#{field.name}"
70
- elsif (field.sortable.is_a?(String) || field.sortable.is_a?(Symbol)) && field.sortable.to_s.include?('.') # just provide sortable, don't do anything smart
71
- field.sortable
72
- elsif field.sortable.is_a?(Hash) # just join sortable hash, don't do anything smart
73
- "#{field.sortable.keys.first}.#{field.sortable.values.first}"
74
- elsif field.association? # use column on target table
75
- "#{field.associated_model_config.abstract_model.table_name}.#{field.sortable}"
76
- else # use described column in the field conf.
77
- "#{abstract_model.table_name}.#{field.sortable}"
69
+ model_config.list.sort_by
70
+ else
71
+ field.sort_column
78
72
  end
79
73
 
80
74
  params[:sort_reverse] ||= 'false'
@@ -129,7 +123,8 @@ module RailsAdmin
129
123
  end
130
124
 
131
125
  def get_collection(model_config, scope, pagination)
132
- eager_loads = model_config.list.fields.flat_map(&:eager_load_values)
126
+ section = @action.key == :export ? model_config.export : model_config.list
127
+ eager_loads = section.fields.flat_map(&:eager_load_values)
133
128
  options = {}
134
129
  options = options.merge(page: (params[Kaminari.config.param_name] || 1).to_i, per: (params[:per] || model_config.list.items_per_page)) if pagination
135
130
  options = options.merge(include: eager_loads) unless eager_loads.blank?
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RailsAdmin
2
4
  module ApplicationHelper
3
5
  def authorized?(action_name, abstract_model = nil, object = nil)
@@ -29,7 +31,7 @@ module RailsAdmin
29
31
 
30
32
  if authorized
31
33
  edit_url = rails_admin.url_for(
32
- action_name: edit_action.action_name,
34
+ action: edit_action.action_name,
33
35
  model_name: abstract_model.to_param,
34
36
  controller: 'rails_admin/main',
35
37
  id: _current_user.id,
@@ -84,7 +86,7 @@ module RailsAdmin
84
86
 
85
87
  label = navigation_label || t('admin.misc.navigation')
86
88
 
87
- %(<li class='dropdown-header'>#{label}</li>#{li_stack}) if li_stack.present?
89
+ collapsible_stack(label, 'main', li_stack)
88
90
  end.join.html_safe
89
91
  end
90
92
 
@@ -99,18 +101,17 @@ module RailsAdmin
99
101
  end.join.html_safe
100
102
  label ||= t('admin.misc.root_navigation')
101
103
 
102
- %(<li class='dropdown-header'>#{label}</li>#{li_stack}) if li_stack.present?
104
+ collapsible_stack(label, 'action', li_stack)
103
105
  end.join.html_safe
104
106
  end
105
107
 
106
108
  def static_navigation
107
109
  li_stack = RailsAdmin::Config.navigation_static_links.collect do |title, url|
108
110
  content_tag(:li, link_to(title.to_s, url, target: '_blank', rel: 'noopener noreferrer', class: 'nav-link'))
109
- end.join
111
+ end.join.html_safe
110
112
 
111
113
  label = RailsAdmin::Config.navigation_static_label || t('admin.misc.navigation_static_label')
112
- li_stack = %(<li class='dropdown-header'>#{label}</li>#{li_stack}).html_safe if li_stack.present?
113
- li_stack
114
+ collapsible_stack(label, 'static', li_stack) || ''
114
115
  end
115
116
 
116
117
  def navigation(parent_groups, nodes, level = 0)
@@ -118,10 +119,12 @@ module RailsAdmin
118
119
  abstract_model = node.abstract_model
119
120
  model_param = abstract_model.to_param
120
121
  url = rails_admin.url_for(action: :index, controller: 'rails_admin/main', model_name: model_param)
121
- level_class = " nav-level-#{level}" if level > 0
122
122
  nav_icon = node.navigation_icon ? %(<i class="#{node.navigation_icon}"></i>).html_safe : ''
123
+ css_classes = ['nav-link']
124
+ css_classes.push("nav-level-#{level}") if level > 0
125
+ css_classes.push('active') if defined?(@action) && current_action?(@action, model_param)
123
126
  li = content_tag :li, data: {model: model_param} do
124
- link_to nav_icon + node.label_plural, url, class: "nav-link#{level_class}"
127
+ link_to nav_icon + " " + node.label_plural, url, class: css_classes.join(' ')
125
128
  end
126
129
  child_nodes = parent_groups[abstract_model.model_name]
127
130
  child_nodes ? li + navigation(parent_groups, child_nodes, level + 1) : li
@@ -206,7 +209,7 @@ module RailsAdmin
206
209
  yield
207
210
  rescue LoadError => e
208
211
  if /sassc/.match?(e.message)
209
- e = e.exception <<-MSG.gsub(/^\s{10}/, '')
212
+ e = e.exception <<~MSG
210
213
  #{e.message}
211
214
  RailsAdmin requires the gem sassc-rails, make sure to put `gem 'sassc-rails'` to Gemfile.
212
215
  MSG
@@ -214,6 +217,15 @@ module RailsAdmin
214
217
  raise e
215
218
  end
216
219
 
220
+ # Workaround for https://github.com/rails/rails/issues/31325
221
+ def image_tag(source, options = {})
222
+ if %w[ActiveStorage::Variant ActiveStorage::VariantWithRecord ActiveStorage::Preview].include? source.class.to_s
223
+ super main_app.route_for(ActiveStorage.resolve_model_to_route, source), options
224
+ else
225
+ super
226
+ end
227
+ end
228
+
217
229
  private
218
230
 
219
231
  def edit_user_link_label
@@ -228,5 +240,21 @@ module RailsAdmin
228
240
  def gravatar_url(email)
229
241
  "https://secure.gravatar.com/avatar/#{Digest::MD5.hexdigest email}?s=30"
230
242
  end
243
+
244
+ def collapsible_stack(label, class_prefix, li_stack)
245
+ return nil unless li_stack.present?
246
+
247
+ collapse_classname = "#{class_prefix}-#{Digest::MD5.hexdigest(label)[0..7]}"
248
+ content_tag(:li, class: 'mb-1') do
249
+ content_tag(:button, 'aria-expanded': true, class: 'btn btn-toggle align-items-center rounded', data: {bs_toggle: "collapse", bs_target: ".sidebar .#{collapse_classname}"}) do
250
+ content_tag(:i, '', class: 'fas fa-chevron-down') + html_escape(' ' + label)
251
+ end +
252
+ content_tag(:div, class: "collapse show #{collapse_classname}") do
253
+ content_tag(:ul, class: 'btn-toggle-nav list-unstyled fw-normal pb-1') do
254
+ li_stack
255
+ end
256
+ end
257
+ end
258
+ end
231
259
  end
232
260
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'nested_form/builder_mixin'
2
4
 
3
5
  module RailsAdmin
@@ -105,6 +107,14 @@ module RailsAdmin
105
107
  (@dom_name ||= {})[field.name] ||= %(#{@object_name}#{options[:index] && "[#{options[:index]}]"}[#{field.method_name}]#{field.is_a?(Config::Fields::Association) && field.multiple? ? '[]' : ''})
106
108
  end
107
109
 
110
+ def hidden_field(method, options = {})
111
+ if method == :id
112
+ super method, {value: object.id.to_s}
113
+ else
114
+ super
115
+ end
116
+ end
117
+
108
118
  protected
109
119
 
110
120
  def generator_action(action, nested)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module RailsAdmin
2
4
  module MainHelper
3
5
  def rails_admin_form_for(*args, &block)
@@ -40,7 +42,6 @@ module RailsAdmin
40
42
  def ordered_filter_options
41
43
  if ordered_filters
42
44
  @ordered_filter_options ||= ordered_filters.map do |duplet|
43
- options = {index: duplet[0]}
44
45
  filter_for_field = duplet[1]
45
46
  filter_name = filter_for_field.keys.first
46
47
  filter_hash = filter_for_field.values.first
@@ -48,20 +49,11 @@ module RailsAdmin
48
49
  raise "#{filter_name} is not currently filterable; filterable fields are #{filterable_fields.map(&:name).join(', ')}"
49
50
  end
50
51
 
51
- case field.type
52
- when :enum
53
- options[:select_options] = options_for_select(field.with(object: @abstract_model.model.new).enum, filter_hash['v'])
54
- when :date, :datetime, :time
55
- options[:datetimepicker_options] = field.datepicker_options
56
- end
57
- options[:label] = field.label
58
- options[:name] = field.name
59
- options[:type] = field.type
60
- options[:value] = filter_hash['v']
61
- options[:label] = field.label
62
- options[:operator] = filter_hash['o'] || field.default_filter_operator
63
- options[:required] = field.required
64
- options
52
+ field.filter_options.merge(
53
+ index: duplet[0],
54
+ operator: filter_hash['o'] || field.default_filter_operator,
55
+ value: filter_hash['v'],
56
+ )
65
57
  end
66
58
  end
67
59
  end
@@ -6,15 +6,24 @@
6
6
  <% case RailsAdmin::config.asset_source
7
7
  when :webpacker %>
8
8
  <%= stylesheet_pack_tag "rails_admin", data: {'turbo-track': 'reload'} %>
9
- <%= javascript_pack_tag "rails_admin", async: true, data: {'turbo-track': 'reload'} %>
9
+ <%= javascript_pack_tag "rails_admin", defer: true, data: {'turbo-track': 'reload'} %>
10
10
  <% when :sprockets %>
11
11
  <% handle_asset_dependency_error do %>
12
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'} %>
13
+ <%= javascript_include_tag "rails_admin/application.js", defer: true, data: {'turbo-track': 'reload'} %>
14
14
  <% end %>
15
15
  <% when :webpack %>
16
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'} %>
17
+ <%= javascript_include_tag "rails_admin.js", defer: true, data: {'turbo-track': 'reload'} %>
18
+ <% when :importmap %>
19
+ <%= stylesheet_link_tag "rails_admin.css", media: :all, data: {'turbo-track': 'reload'} %>
20
+ <%= javascript_inline_importmap_tag(RailsAdmin::Engine.importmap.to_json(resolver: self)) %>
21
+ <%= javascript_importmap_module_preload_tags(RailsAdmin::Engine.importmap) %>
22
+ <%= javascript_importmap_shim_nonce_configuration_tag %>
23
+ <%= javascript_importmap_shim_tag %>
24
+ <%= # Preload jQuery and make it global, unless jQuery UI fails to initialize
25
+ tag.script "import jQuery from 'jquery'; window.jQuery = jQuery;".html_safe, type: "module" %>
26
+ <%= javascript_import_module_tag 'rails_admin' %>
18
27
  <% else
19
28
  raise "Unknown asset_source: #{RailsAdmin::config.asset_source}"
20
29
  end %>
@@ -17,7 +17,9 @@
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', data: {turbo: 'false'} %>
20
+ <%= link_to logout_path, method: logout_method, class: 'nav-link', data: {turbo: 'false'} do %>
21
+ <span class="badge bg-danger"><%= t('admin.misc.log_out') %></span>
22
+ <% end %>
21
23
  </li>
22
24
  <% end %>
23
25
  <% end %>
@@ -1,4 +1,4 @@
1
- <ul class="col-sm-3 col-md-2 btn-toggle-nav list-unstyled bg-light">
1
+ <ul class="sidebar col-sm-3 col-md-2 nav btn-toggle-nav flex-column bg-light">
2
2
  <%= main_navigation %>
3
3
  <%= root_navigation %>
4
4
  <%= static_navigation %>
@@ -5,7 +5,10 @@
5
5
  </head>
6
6
  <body class="rails_admin">
7
7
  <div data-i18n-options="<%= I18n.t("admin.js").to_json %>" id="admin-js"></div>
8
- <nav class="navbar navbar-expand-md fixed-top navbar-dark bg-primary border-bottom">
8
+ <div class="badge bg-warning" id="loading" style="display:none; position:fixed; right:20px; bottom:20px; z-index:100000">
9
+ <%= t('admin.loading') %>
10
+ </div>
11
+ <nav class="navbar navbar-expand-md fixed-top <%= RailsAdmin::Config.navbar_css_classes.join(' ') %>">
9
12
  <%= render "layouts/rails_admin/navigation" %>
10
13
  </nav>
11
14
  <div class="container-fluid">
@@ -12,7 +12,7 @@
12
12
  </th>
13
13
  </tr>
14
14
  </thead>
15
- <tbody>
15
+ <tbody class="table-group-divider">
16
16
  <% @history.each do |t| %>
17
17
  <% abstract_model = RailsAdmin.config(t.table).abstract_model %>
18
18
  <tr>
@@ -1,7 +1,8 @@
1
1
  <%
2
2
  js_data = {
3
3
  csspath: field.css_location,
4
- jspath: field.js_location
4
+ jspath: field.js_location,
5
+ warn_dynamic_load: field.warn_dynamic_load
5
6
  }
6
7
  %>
7
8
  <%= form.rich_text_area field.method_name, field.html_attributes.reverse_merge(data: { options: js_data.to_json }) %>
@@ -6,7 +6,7 @@
6
6
  <% if value = field.pretty_value %>
7
7
  <%= value %>
8
8
  <% end %>
9
- <%= form.file_field(field.name, field.html_attributes.reverse_merge({ data: { fileupload: true }})) %>
9
+ <%= form.file_field(field.name, {data: {fileupload: true}}.deep_merge(field.html_attributes)) %>
10
10
  </div>
11
11
  <% if field.optional? && field.errors.blank? && file && field.delete_method %>
12
12
  <a class="btn btn-info btn-remove-image" data-toggle="button" href="#" role="button">
@@ -3,7 +3,7 @@
3
3
  source_abstract_model = RailsAdmin.config(form.object.class).abstract_model
4
4
 
5
5
  selected = form.object.send(field.name)
6
- selected_ids = selected.map{|s| s.send(field.associated_primary_key)}
6
+ selected_ids = selected.map{|s| s.send(field.associated_primary_key).to_s}
7
7
 
8
8
  current_action = params[:action].in?(['create', 'new']) ? 'create' : 'update'
9
9
 
@@ -13,7 +13,7 @@
13
13
  selected.map { |o| [o.send(field.associated_object_label_method), o.send(field.associated_primary_key)] }
14
14
  else
15
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)] }.sort_by {|a| [selected_ids.index(a[1]) || selected_ids.size, i+=1] }
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
17
  end
18
18
 
19
19
  js_data = {
@@ -8,7 +8,7 @@
8
8
 
9
9
  xhr = !field.associated_collection_cache_all
10
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)] }
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
12
 
13
13
  js_data = {
14
14
  xhr: xhr,
@@ -14,7 +14,7 @@
14
14
  <% end %>
15
15
  </div>
16
16
  <% end %>
17
- <%= form.file_field(field.name, field.html_attributes.reverse_merge({ data: { :"multiple-fileupload" => true }, multiple: true })) %>
17
+ <%= form.file_field(field.name, { data: { :"multiple-fileupload" => true }, multiple: true }.deep_merge(field.html_attributes)) %>
18
18
  <% if field.cache_method %>
19
19
  <%= form.hidden_field(field.cache_method) %>
20
20
  <% end %>
@@ -14,7 +14,7 @@
14
14
  <th class="shrink controls"></th>
15
15
  </tr>
16
16
  </thead>
17
- <tbody>
17
+ <tbody class="table-group-divider">
18
18
  <% @abstract_models.each do |abstract_model| %>
19
19
  <% if authorized? :index, abstract_model %>
20
20
  <% index_path = index_path(model_name: abstract_model.to_param) %>
@@ -42,7 +42,7 @@
42
42
  </div>
43
43
  </td>
44
44
  <td class="links">
45
- <ul class="inline list-inline">
45
+ <ul class="nav d-inline list-inline">
46
46
  <%= menu_for :collection, abstract_model, nil, true %>
47
47
  </ul>
48
48
  </td>
@@ -38,7 +38,7 @@
38
38
  <% end %>
39
39
  </tr>
40
40
  </thead>
41
- <tbody>
41
+ <tbody class="table-group-divider">
42
42
  <% @history.each_with_index do |object, index| %>
43
43
  <tr>
44
44
  <% unless object.created_at.nil? %>
@@ -26,26 +26,11 @@
26
26
  </a>
27
27
  <ul class="dropdown-menu dropdown-menu-end" id="filters">
28
28
  <% filterable_fields.each do |field| %>
29
- <%
30
- field_options = case field.type
31
- when :enum
32
- options_for_select(field.with(object: @abstract_model.model.new).enum)
33
- else
34
- ''
35
- end
36
- %>
37
29
  <li>
38
30
  <a
39
31
  href="#"
40
32
  class="dropdown-item"
41
- data-field-label="<%= field.label %>"
42
- data-field-name="<%= field.name %>"
43
- data-field-operator="<%= field.default_filter_operator %>"
44
- data-field-options="<%= "#{field_options}" %>"
45
- data-field-required="<%= field.required.to_s %>"
46
- data-field-type="<%= field.type %>"
47
- data-field-value=""
48
- data-field-datetimepicker-options="<%= field.try(:datepicker_options).try(:to_json) %>"
33
+ data-options="<%= field.with(view: self).filter_options.to_json %>"
49
34
  >
50
35
  <%= field.label %>
51
36
  </a>
@@ -83,6 +68,9 @@
83
68
  <i class="fas fa-times"></i>
84
69
  </button>
85
70
  </div>
71
+ <% if @model_config.list.search_help.present? %>
72
+ <div class="form-text"><%= @model_config.list.search_help %></div>
73
+ <% end %>
86
74
  </div>
87
75
  <div class="col-sm-6 text-end">
88
76
  <% if export_action %>
@@ -135,12 +123,12 @@
135
123
  <th class="last shrink"></th>
136
124
  </tr>
137
125
  </thead>
138
- <tbody>
126
+ <tbody class="table-group-divider">
139
127
  <% @objects.each do |object| %>
140
128
  <tr class="<%= @abstract_model.param_key %>_row <%= @model_config.list.with(object: object).row_css_class %>">
141
129
  <% if checkboxes %>
142
130
  <td class="sticky">
143
- <%= check_box_tag "bulk_ids[]", object.id, false %>
131
+ <%= check_box_tag "bulk_ids[]", object.id.to_s, false %>
144
132
  </td>
145
133
  <% end %>
146
134
  <% properties.map{ |property| property.bind(:object, object) }.each do |property| %>
@@ -150,7 +138,7 @@
150
138
  </td>
151
139
  <% end %>
152
140
  <td class="last links ra-sidescroll-frozen">
153
- <ul class="inline list-inline">
141
+ <ul class="nav d-inline list-inline">
154
142
  <%= menu_for :member, @abstract_model, object, true %>
155
143
  </ul>
156
144
  </td>
@@ -1,10 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  ActiveSupport.on_load(:active_record) do
2
4
  module ActiveRecord
3
5
  class Base
4
6
  def self.rails_admin(&block)
5
- RailsAdmin.config do |config|
6
- config.model(self, &block)
7
- end
7
+ RailsAdmin.config(self, &block)
8
8
  end
9
9
 
10
10
  def rails_admin_default_object_label_method
@@ -20,4 +20,27 @@ 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
23
46
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  if defined?(::Mongoid::Document)
2
4
  require 'rails_admin/adapters/mongoid/extension'
3
5
  Mongoid::Document.include RailsAdmin::Adapters::Mongoid::Extension
@@ -1,8 +1,8 @@
1
1
  en:
2
2
  admin:
3
3
  js:
4
- true: True
5
- false: False
4
+ true: "True"
5
+ false: "False"
6
6
  is_present: Is present
7
7
  is_blank: Is blank
8
8
  date: Date ...
@@ -21,6 +21,7 @@ en:
21
21
  too_many_objects: "Too many objects, use search box above"
22
22
  no_objects: "No objects found"
23
23
  clear: Clear
24
+ loading: "Loading..."
24
25
  toggle_navigation: Toggle navigation
25
26
  home:
26
27
  name: "Home"
data/config/routes.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  RailsAdmin::Engine.routes.draw do
2
4
  controller 'main' do
3
5
  RailsAdmin::Config::Actions.all(:root).each { |action| match "/#{action.route_fragment}", action: action.action_name, as: action.action_name, via: action.http_methods }
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'importmap/packager'
4
+
5
+ module RailsAdmin
6
+ class ImportmapFormatter
7
+ attr_reader :packager
8
+
9
+ def initialize(path = 'confing/importmap.rails_admin.rb')
10
+ @packager = Importmap::Packager.new(path)
11
+ end
12
+
13
+ def format
14
+ imports = packager.import("rails_admin@#{RailsAdmin::Version.js}")
15
+
16
+ # Use ESM compatible version to work around https://github.com/cljsjs/packages/issues/1579
17
+ imports['@popperjs/core'].gsub!('lib/index.js', 'dist/esm/popper.js')
18
+
19
+ # Tidy up jQuery UI dependencies
20
+ jquery_uis = imports.keys.filter { |key, _| key =~ /jquery-ui/ }
21
+ imports['jquery-ui/'] = imports[jquery_uis.first].gsub(%r{(@[^/@]+)/[^@]+$}, '\1/')
22
+ imports.reject! { |key, _| jquery_uis.include? key }
23
+
24
+ pins = ['pin "rails_admin", preload: true', packager.pin_for('rails_admin/src/rails_admin/base', imports.delete('rails_admin'))]
25
+ (pins + imports.map { |package, url| packager.pin_for(package, url) }).join("\n")
26
+ end
27
+ end
28
+ end