rails_admin 3.0.0 → 3.1.0.rc

Sign up to get free protection for your applications and to get access to all the features.
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 +9 -0
  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 +4 -2
  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 +17 -14
  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: 19012148f5f945b4c04e703c7f97fb74ded0442755eb953a130a81a5d58302ab
4
+ data.tar.gz: ecd7599be265ad2cbfcb2c7c09dc16afb470ca663d1d5eb6b0c0504b5770b46c
5
5
  SHA512:
6
- metadata.gz: ea7b4265126ff76473d461cd0630feb1a4e3ad71476d2843577a25fdaea53fed0ca57b06b55dbe63615f5004151796b346f9bca2492ff71175d44faffbe24c38
7
- data.tar.gz: 58fb832bd8e1e7c124e79eabd01393da73217714e0b52a32ea215ef1e1b2d4f33390928ed15686eeed983446d74a914ac947cd709bd67180799bf8bd9017bc4a
6
+ metadata.gz: 2c115d8a5729876233ab0980bec1398301f9c40c4d77799570c993fb521c7f9aa8b45639a308a3cd2dab2591a1455c42d793fb40875c58d4cb6896c345ec28dc
7
+ data.tar.gz: 6cb2d93962b016f5b21034958d661ec624c1553cb0aeb0be3d74c07c4fbab33fe8e15f2d1910ac6d5aec1b250d95a45f71a0faf1fc365a952c6fe9a80bceb6f1
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
@@ -15,6 +15,15 @@
15
15
  <% when :webpack %>
16
16
  <%= stylesheet_link_tag "rails_admin.css", media: :all, data: {'turbo-track': 'reload'} %>
17
17
  <%= javascript_include_tag "rails_admin.js", async: 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 list-unstyled 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