rails_admin_next 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (184) hide show
  1. checksums.yaml +7 -0
  2. data/Gemfile +46 -0
  3. data/LICENSE.md +21 -0
  4. data/README.md +317 -0
  5. data/Rakefile +25 -0
  6. data/app/assets/javascripts/rails_admin/custom/ui.js +1 -0
  7. data/app/assets/stylesheets/rails_admin/framework.css +2375 -0
  8. data/app/assets/stylesheets/rails_admin/skin.css +472 -0
  9. data/app/assets/stylesheets/rails_admin/tokens.css +281 -0
  10. data/app/assets/stylesheets/rails_admin.css +47 -0
  11. data/app/controllers/rails_admin_next/application_controller.rb +98 -0
  12. data/app/controllers/rails_admin_next/main_controller.rb +185 -0
  13. data/app/helpers/rails_admin_next/application_helper.rb +254 -0
  14. data/app/helpers/rails_admin_next/form_builder.rb +173 -0
  15. data/app/helpers/rails_admin_next/main_helper.rb +63 -0
  16. data/app/views/layouts/rails_admin_next/_head.html.erb +29 -0
  17. data/app/views/layouts/rails_admin_next/_navigation.html.erb +18 -0
  18. data/app/views/layouts/rails_admin_next/_secondary_navigation.html.erb +27 -0
  19. data/app/views/layouts/rails_admin_next/_sidebar_navigation.html.erb +6 -0
  20. data/app/views/layouts/rails_admin_next/application.html.erb +42 -0
  21. data/app/views/layouts/rails_admin_next/content.html.erb +22 -0
  22. data/app/views/layouts/rails_admin_next/modal.js.erb +7 -0
  23. data/app/views/rails_admin_next/main/_dashboard_history.html.erb +46 -0
  24. data/app/views/rails_admin_next/main/_delete_notice.html.erb +36 -0
  25. data/app/views/rails_admin_next/main/_form_action_text.html.erb +2 -0
  26. data/app/views/rails_admin_next/main/_form_boolean.html.erb +15 -0
  27. data/app/views/rails_admin_next/main/_form_colorpicker.html.erb +6 -0
  28. data/app/views/rails_admin_next/main/_form_datetime.html.erb +14 -0
  29. data/app/views/rails_admin_next/main/_form_enumeration.html.erb +26 -0
  30. data/app/views/rails_admin_next/main/_form_field.html.erb +2 -0
  31. data/app/views/rails_admin_next/main/_form_file_upload.html.erb +18 -0
  32. data/app/views/rails_admin_next/main/_form_filtering_multiselect.html.erb +20 -0
  33. data/app/views/rails_admin_next/main/_form_filtering_select.html.erb +22 -0
  34. data/app/views/rails_admin_next/main/_form_multiple_file_upload.html.erb +21 -0
  35. data/app/views/rails_admin_next/main/_form_nested_many.html.erb +20 -0
  36. data/app/views/rails_admin_next/main/_form_nested_one.html.erb +19 -0
  37. data/app/views/rails_admin_next/main/_form_polymorphic_association.html.erb +24 -0
  38. data/app/views/rails_admin_next/main/_form_text.html.erb +2 -0
  39. data/app/views/rails_admin_next/main/_pagination.html.erb +54 -0
  40. data/app/views/rails_admin_next/main/_submit_buttons.html.erb +26 -0
  41. data/app/views/rails_admin_next/main/bulk_delete.html.erb +19 -0
  42. data/app/views/rails_admin_next/main/dashboard.html.erb +64 -0
  43. data/app/views/rails_admin_next/main/delete.html.erb +21 -0
  44. data/app/views/rails_admin_next/main/edit.html.erb +3 -0
  45. data/app/views/rails_admin_next/main/export.html.erb +149 -0
  46. data/app/views/rails_admin_next/main/history.html.erb +80 -0
  47. data/app/views/rails_admin_next/main/index.html.erb +186 -0
  48. data/app/views/rails_admin_next/main/new.html.erb +3 -0
  49. data/app/views/rails_admin_next/main/show.html.erb +30 -0
  50. data/config/brakeman.ignore +145 -0
  51. data/config/importmap.rails_admin.rb +29 -0
  52. data/config/initializers/active_record_extensions.rb +21 -0
  53. data/config/locales/rails_admin_next.en.yml +158 -0
  54. data/config/routes.rb +14 -0
  55. data/lib/generators/rails_admin_next/install_generator.rb +39 -0
  56. data/lib/generators/rails_admin_next/templates/initializer.erb +40 -0
  57. data/lib/generators/rails_admin_next/utils.rb +21 -0
  58. data/lib/rails_admin_next/abstract_model.rb +266 -0
  59. data/lib/rails_admin_next/adapters/active_record/association.rb +130 -0
  60. data/lib/rails_admin_next/adapters/active_record/object_extension.rb +13 -0
  61. data/lib/rails_admin_next/adapters/active_record/property.rb +58 -0
  62. data/lib/rails_admin_next/adapters/active_record.rb +371 -0
  63. data/lib/rails_admin_next/config/actions/base.rb +160 -0
  64. data/lib/rails_admin_next/config/actions/bulk_delete.rb +67 -0
  65. data/lib/rails_admin_next/config/actions/dashboard.rb +62 -0
  66. data/lib/rails_admin_next/config/actions/delete.rb +58 -0
  67. data/lib/rails_admin_next/config/actions/edit.rb +56 -0
  68. data/lib/rails_admin_next/config/actions/export.rb +47 -0
  69. data/lib/rails_admin_next/config/actions/history_index.rb +40 -0
  70. data/lib/rails_admin_next/config/actions/history_show.rb +40 -0
  71. data/lib/rails_admin_next/config/actions/index.rb +108 -0
  72. data/lib/rails_admin_next/config/actions/new.rb +69 -0
  73. data/lib/rails_admin_next/config/actions/show.rb +36 -0
  74. data/lib/rails_admin_next/config/actions/show_in_app.rb +37 -0
  75. data/lib/rails_admin_next/config/actions.rb +122 -0
  76. data/lib/rails_admin_next/config/configurable.rb +107 -0
  77. data/lib/rails_admin_next/config/const_load_suppressor.rb +78 -0
  78. data/lib/rails_admin_next/config/fields/association.rb +169 -0
  79. data/lib/rails_admin_next/config/fields/base.rb +391 -0
  80. data/lib/rails_admin_next/config/fields/collection_association.rb +90 -0
  81. data/lib/rails_admin_next/config/fields/factories/action_text.rb +14 -0
  82. data/lib/rails_admin_next/config/fields/factories/active_storage.rb +34 -0
  83. data/lib/rails_admin_next/config/fields/factories/association.rb +32 -0
  84. data/lib/rails_admin_next/config/fields/factories/encrypted_password.rb +28 -0
  85. data/lib/rails_admin_next/config/fields/factories/enum.rb +23 -0
  86. data/lib/rails_admin_next/config/fields/factories/password.rb +19 -0
  87. data/lib/rails_admin_next/config/fields/group.rb +77 -0
  88. data/lib/rails_admin_next/config/fields/singular_association.rb +62 -0
  89. data/lib/rails_admin_next/config/fields/types/action_text.rb +20 -0
  90. data/lib/rails_admin_next/config/fields/types/active_record_enum.rb +62 -0
  91. data/lib/rails_admin_next/config/fields/types/active_storage.rb +70 -0
  92. data/lib/rails_admin_next/config/fields/types/all.rb +32 -0
  93. data/lib/rails_admin_next/config/fields/types/belongs_to_association.rb +48 -0
  94. data/lib/rails_admin_next/config/fields/types/boolean.rb +70 -0
  95. data/lib/rails_admin_next/config/fields/types/citext.rb +15 -0
  96. data/lib/rails_admin_next/config/fields/types/color.rb +43 -0
  97. data/lib/rails_admin_next/config/fields/types/date.rb +38 -0
  98. data/lib/rails_admin_next/config/fields/types/datetime.rb +79 -0
  99. data/lib/rails_admin_next/config/fields/types/decimal.rb +23 -0
  100. data/lib/rails_admin_next/config/fields/types/enum.rb +52 -0
  101. data/lib/rails_admin_next/config/fields/types/file_upload.rb +87 -0
  102. data/lib/rails_admin_next/config/fields/types/float.rb +23 -0
  103. data/lib/rails_admin_next/config/fields/types/has_and_belongs_to_many_association.rb +16 -0
  104. data/lib/rails_admin_next/config/fields/types/has_many_association.rb +16 -0
  105. data/lib/rails_admin_next/config/fields/types/has_one_association.rb +35 -0
  106. data/lib/rails_admin_next/config/fields/types/hidden.rb +31 -0
  107. data/lib/rails_admin_next/config/fields/types/inet.rb +15 -0
  108. data/lib/rails_admin_next/config/fields/types/integer.rb +20 -0
  109. data/lib/rails_admin_next/config/fields/types/json.rb +37 -0
  110. data/lib/rails_admin_next/config/fields/types/multiple_active_storage.rb +82 -0
  111. data/lib/rails_admin_next/config/fields/types/multiple_file_upload.rb +134 -0
  112. data/lib/rails_admin_next/config/fields/types/numeric.rb +24 -0
  113. data/lib/rails_admin_next/config/fields/types/password.rb +45 -0
  114. data/lib/rails_admin_next/config/fields/types/polymorphic_association.rb +118 -0
  115. data/lib/rails_admin_next/config/fields/types/serialized.rb +28 -0
  116. data/lib/rails_admin_next/config/fields/types/string.rb +50 -0
  117. data/lib/rails_admin_next/config/fields/types/string_like.rb +25 -0
  118. data/lib/rails_admin_next/config/fields/types/text.rb +28 -0
  119. data/lib/rails_admin_next/config/fields/types/time.rb +39 -0
  120. data/lib/rails_admin_next/config/fields/types/timestamp.rb +16 -0
  121. data/lib/rails_admin_next/config/fields/types/uuid.rb +15 -0
  122. data/lib/rails_admin_next/config/fields/types.rb +29 -0
  123. data/lib/rails_admin_next/config/fields.rb +88 -0
  124. data/lib/rails_admin_next/config/groupable.rb +20 -0
  125. data/lib/rails_admin_next/config/has_description.rb +14 -0
  126. data/lib/rails_admin_next/config/has_fields.rb +144 -0
  127. data/lib/rails_admin_next/config/has_groups.rb +27 -0
  128. data/lib/rails_admin_next/config/hideable.rb +30 -0
  129. data/lib/rails_admin_next/config/inspectable.rb +39 -0
  130. data/lib/rails_admin_next/config/lazy_model.rb +74 -0
  131. data/lib/rails_admin_next/config/model.rb +126 -0
  132. data/lib/rails_admin_next/config/proxyable/proxy.rb +42 -0
  133. data/lib/rails_admin_next/config/proxyable.rb +26 -0
  134. data/lib/rails_admin_next/config/sections/base.rb +36 -0
  135. data/lib/rails_admin_next/config/sections/create.rb +13 -0
  136. data/lib/rails_admin_next/config/sections/edit.rb +13 -0
  137. data/lib/rails_admin_next/config/sections/export.rb +13 -0
  138. data/lib/rails_admin_next/config/sections/list.rb +63 -0
  139. data/lib/rails_admin_next/config/sections/modal.rb +12 -0
  140. data/lib/rails_admin_next/config/sections/nested.rb +12 -0
  141. data/lib/rails_admin_next/config/sections/show.rb +12 -0
  142. data/lib/rails_admin_next/config/sections/update.rb +12 -0
  143. data/lib/rails_admin_next/config/sections.rb +39 -0
  144. data/lib/rails_admin_next/config.rb +436 -0
  145. data/lib/rails_admin_next/engine.rb +91 -0
  146. data/lib/rails_admin_next/extension.rb +35 -0
  147. data/lib/rails_admin_next/extensions/cancancan/authorization_adapter.rb +90 -0
  148. data/lib/rails_admin_next/extensions/cancancan.rb +5 -0
  149. data/lib/rails_admin_next/extensions/controller_extension.rb +8 -0
  150. data/lib/rails_admin_next/extensions/paper_trail/auditing_adapter.rb +192 -0
  151. data/lib/rails_admin_next/extensions/paper_trail.rb +5 -0
  152. data/lib/rails_admin_next/extensions/pundit/authorization_adapter.rb +72 -0
  153. data/lib/rails_admin_next/extensions/pundit.rb +5 -0
  154. data/lib/rails_admin_next/extensions/url_for_extension.rb +15 -0
  155. data/lib/rails_admin_next/icons.rb +143 -0
  156. data/lib/rails_admin_next/support/composite_keys_serializer.rb +15 -0
  157. data/lib/rails_admin_next/support/csv_converter.rb +100 -0
  158. data/lib/rails_admin_next/support/hash_helper.rb +31 -0
  159. data/lib/rails_admin_next/support/paginated_collection.rb +79 -0
  160. data/lib/rails_admin_next/version.rb +17 -0
  161. data/lib/rails_admin_next.rb +72 -0
  162. data/lib/tasks/rails_admin.rake +40 -0
  163. data/src/rails_admin/application.js +15 -0
  164. data/src/rails_admin/base.js +12 -0
  165. data/src/rails_admin/controllers/alert_controller.js +28 -0
  166. data/src/rails_admin/controllers/collapse_controller.js +16 -0
  167. data/src/rails_admin/controllers/dropdown_controller.js +110 -0
  168. data/src/rails_admin/controllers/feedback_controller.js +73 -0
  169. data/src/rails_admin/controllers/filter_box_controller.js +346 -0
  170. data/src/rails_admin/controllers/filtering_multiselect_controller.js +386 -0
  171. data/src/rails_admin/controllers/filtering_select_controller.js +509 -0
  172. data/src/rails_admin/controllers/index.js +31 -0
  173. data/src/rails_admin/controllers/modal_controller.js +142 -0
  174. data/src/rails_admin/controllers/nested_form_controller.js +117 -0
  175. data/src/rails_admin/controllers/polymorphic_controller.js +26 -0
  176. data/src/rails_admin/controllers/remote_form_controller.js +173 -0
  177. data/src/rails_admin/controllers/sidescroll_controller.js +23 -0
  178. data/src/rails_admin/dom-ready.js +20 -0
  179. data/src/rails_admin/dom.js +19 -0
  180. data/src/rails_admin/i18n.js +20 -0
  181. data/src/rails_admin/icons.js +64 -0
  182. data/src/rails_admin/interactions.js +221 -0
  183. data/src/rails_admin/select_query.js +65 -0
  184. metadata +346 -0
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class Dashboard < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :root? do
10
+ true
11
+ end
12
+
13
+ register_instance_option :breadcrumb_parent do
14
+ nil
15
+ end
16
+
17
+ register_instance_option :auditing_versions_limit do
18
+ 100
19
+ end
20
+
21
+ register_instance_option :controller do
22
+ proc do
23
+ @history = @auditing_adapter&.latest(@action.auditing_versions_limit) if @action.history?
24
+ if @action.statistics?
25
+ model_configs = RailsAdminNext::Config.visible_models(controller: self)
26
+
27
+ @abstract_models = model_configs.map(&:abstract_model)
28
+ @most_recent_created = {}
29
+ @count = {}
30
+ @max = 0
31
+ model_configs.each do |config|
32
+ scope = @authorization_adapter&.query(:index, config.abstract_model)
33
+ current_count = config.abstract_model.count({}, scope)
34
+ @max = (current_count > @max) ? current_count : @max
35
+ name = config.abstract_model.model.name
36
+ @count[name] = current_count
37
+ @most_recent_created[name] = config.last_created_at
38
+ end
39
+ end
40
+ render @action.template_name, status: @status_code || :ok
41
+ end
42
+ end
43
+
44
+ register_instance_option :route_fragment do
45
+ ""
46
+ end
47
+
48
+ register_instance_option :link_icon do
49
+ :dashboard
50
+ end
51
+
52
+ register_instance_option :statistics? do
53
+ true
54
+ end
55
+
56
+ register_instance_option :history? do
57
+ true
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class Delete < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :member do
10
+ true
11
+ end
12
+
13
+ register_instance_option :route_fragment do
14
+ "delete"
15
+ end
16
+
17
+ register_instance_option :http_methods do
18
+ %i[get delete]
19
+ end
20
+
21
+ register_instance_option :authorization_key do
22
+ :destroy
23
+ end
24
+
25
+ register_instance_option :controller do
26
+ proc do
27
+ if request.get? # DELETE
28
+
29
+ respond_to do |format|
30
+ format.html { render @action.template_name }
31
+ format.js { render @action.template_name, layout: false }
32
+ end
33
+
34
+ elsif request.delete? # DESTROY
35
+
36
+ @auditing_adapter&.delete_object(@object, @abstract_model, _current_user)
37
+ if @object.destroy
38
+ flash[:success] = t("admin.flash.successful", name: @model_config.label, action: t("admin.actions.delete.done"))
39
+ redirect_to index_path
40
+ else
41
+ handle_save_error :delete
42
+ end
43
+
44
+ end
45
+ end
46
+ end
47
+
48
+ register_instance_option :link_icon do
49
+ :delete
50
+ end
51
+
52
+ register_instance_option :writable? do
53
+ !(bindings[:object] && bindings[:object].readonly?)
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,56 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class Edit < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :member do
10
+ true
11
+ end
12
+
13
+ register_instance_option :http_methods do
14
+ %i[get put]
15
+ end
16
+
17
+ register_instance_option :controller do
18
+ proc do
19
+ if request.get? # EDIT
20
+
21
+ respond_to do |format|
22
+ format.html { render @action.template_name }
23
+ format.js { render @action.template_name, layout: "rails_admin_next/modal", content_type: Mime[:html].to_s }
24
+ end
25
+
26
+ elsif request.put? # UPDATE
27
+ sanitize_params_for!(request.xhr? ? :modal : :update)
28
+
29
+ @object.assign_attributes(params[@abstract_model.param_key])
30
+ @authorization_adapter&.authorize(:update, @abstract_model, @object)
31
+ changes = @object.changes
32
+ if @object.save
33
+ @auditing_adapter&.update_object(@object, @abstract_model, _current_user, changes)
34
+ respond_to do |format|
35
+ format.html { redirect_to_on_success }
36
+ format.json { render json: {id: @object.id.to_s, label: @model_config.with(object: @object).object_label} }
37
+ end
38
+ else
39
+ handle_save_error :edit
40
+ end
41
+
42
+ end
43
+ end
44
+ end
45
+
46
+ register_instance_option :link_icon do
47
+ :edit
48
+ end
49
+
50
+ register_instance_option :writable? do
51
+ !(bindings[:object] && bindings[:object].readonly?)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,47 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class Export < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :collection do
10
+ true
11
+ end
12
+
13
+ register_instance_option :http_methods do
14
+ %i[get post]
15
+ end
16
+
17
+ register_instance_option :controller do
18
+ proc do
19
+ format = params[:json] && :json || params[:csv] && :csv || params[:xml] && :xml
20
+ # Stream the table only on a non-GET, CSRF-protected request. GET (forgery-exempt)
21
+ # renders the form so `GET /export?json=1&schema[...]` can't exfiltrate the whole
22
+ # table with attacker-chosen columns; the export form posts back to this same action.
23
+ if format && !request.get?
24
+ request.format = format
25
+ @schema = HashHelper.symbolize(params[:schema].slice(:except, :include, :methods, :only).permit!.to_h) if params[:schema] # to_json and to_xml expect symbols for keys AND values.
26
+ @objects = list_entries(@model_config, :export)
27
+ index
28
+ else
29
+ # A format-suffixed URL (a bookmarked `GET /export.csv`) reaches this branch
30
+ # with request.format already csv/json/xml; render the form explicitly as HTML
31
+ # so the link fails into the form instead of a MissingTemplate error.
32
+ render @action.template_name, formats: :html
33
+ end
34
+ end
35
+ end
36
+
37
+ register_instance_option :bulkable? do
38
+ true
39
+ end
40
+
41
+ register_instance_option :link_icon do
42
+ :export
43
+ end
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class HistoryIndex < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :authorization_key do
10
+ :history
11
+ end
12
+
13
+ register_instance_option :collection do
14
+ true
15
+ end
16
+
17
+ register_instance_option :route_fragment do
18
+ "history"
19
+ end
20
+
21
+ register_instance_option :controller do
22
+ proc do
23
+ @general = true
24
+ @history = @auditing_adapter&.listing_for_model(@abstract_model, params[:query], params[:sort], params[:sort_reverse], params[:all], params[:page]) || []
25
+
26
+ render @action.template_name
27
+ end
28
+ end
29
+
30
+ register_instance_option :template_name do
31
+ :history
32
+ end
33
+
34
+ register_instance_option :link_icon do
35
+ :history
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class HistoryShow < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :authorization_key do
10
+ :history
11
+ end
12
+
13
+ register_instance_option :member do
14
+ true
15
+ end
16
+
17
+ register_instance_option :route_fragment do
18
+ "history"
19
+ end
20
+
21
+ register_instance_option :controller do
22
+ proc do
23
+ @general = false
24
+ @history = @auditing_adapter&.listing_for_object(@abstract_model, @object, params[:query], params[:sort], params[:sort_reverse], params[:all], params[:page]) || []
25
+
26
+ render @action.template_name
27
+ end
28
+ end
29
+
30
+ register_instance_option :template_name do
31
+ :history
32
+ end
33
+
34
+ register_instance_option :link_icon do
35
+ :history
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,108 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class Index < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :collection do
10
+ true
11
+ end
12
+
13
+ register_instance_option :http_methods do
14
+ %i[get post]
15
+ end
16
+
17
+ register_instance_option :route_fragment do
18
+ ""
19
+ end
20
+
21
+ register_instance_option :breadcrumb_parent do
22
+ parent_model = bindings[:abstract_model].try(:config).try(:parent)
23
+ am = parent_model && RailsAdminNext.config(parent_model).try(:abstract_model)
24
+ if am
25
+ [:index, am]
26
+ else
27
+ [:dashboard]
28
+ end
29
+ end
30
+
31
+ register_instance_option :controller do
32
+ proc do
33
+ # Resolve the active list scope (the scope tabs) and fold it into the
34
+ # relation *before* pagination. The paginated collection is a resolved
35
+ # page, not a chainable relation, so a named scope can no longer be
36
+ # appended afterwards.
37
+ unless @objects
38
+ scopes = @model_config.list.scopes
39
+ list_scope =
40
+ if scopes.empty? || params[:scope].blank?
41
+ scopes.first
42
+ elsif scopes.collect(&:to_s).include?(params[:scope])
43
+ params[:scope].to_sym
44
+ end
45
+
46
+ additional_scope = get_association_scope_from_params
47
+ if list_scope
48
+ base_scope = additional_scope
49
+ additional_scope = proc { (base_scope ? instance_eval(&base_scope) : self).send(list_scope) }
50
+ end
51
+
52
+ @objects = list_entries(@model_config, :index, additional_scope)
53
+ end
54
+
55
+ respond_to do |format|
56
+ format.html do
57
+ render @action.template_name, status: @status_code || :ok
58
+ end
59
+
60
+ format.json do
61
+ output =
62
+ if params[:compact]
63
+ if @association
64
+ @association.collection(@objects).collect { |(label, id)| {id: id, label: label} }
65
+ else
66
+ @objects.collect { |object| {id: object.id.to_s, label: object.send(@model_config.object_label_method).to_s} }
67
+ end
68
+ else
69
+ @objects.to_json(@schema)
70
+ end
71
+
72
+ if params[:send_data]
73
+ send_data output, filename: "#{params[:model_name]}_#{DateTime.now.strftime("%Y-%m-%d_%Hh%Mm%S")}.json"
74
+ else
75
+ render json: output, root: false
76
+ end
77
+ end
78
+
79
+ format.xml do
80
+ output = @objects.map { |object| object.serializable_hash(@schema || {}) }.to_xml(root: @abstract_model.model.model_name.plural)
81
+ if params[:send_data]
82
+ send_data output, filename: "#{params[:model_name]}_#{DateTime.now.strftime("%Y-%m-%d_%Hh%Mm%S")}.xml"
83
+ else
84
+ render xml: output
85
+ end
86
+ end
87
+
88
+ format.csv do
89
+ header, encoding, output = CSVConverter.new(@objects, @schema).to_csv(params[:csv_options].permit!.to_h)
90
+ if params[:send_data]
91
+ send_data output,
92
+ type: "text/csv; charset=#{encoding}; #{"header=present" if header}",
93
+ disposition: "attachment; filename=#{params[:model_name]}_#{DateTime.now.strftime("%Y-%m-%d_%Hh%Mm%S")}.csv"
94
+ else
95
+ render plain: output
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+
102
+ register_instance_option :link_icon do
103
+ :list
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class New < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :collection do
10
+ true
11
+ end
12
+
13
+ register_instance_option :http_methods do
14
+ %i[get post] # NEW / CREATE
15
+ end
16
+
17
+ register_instance_option :controller do
18
+ proc do
19
+ if request.get? # NEW
20
+
21
+ @object = @abstract_model.new
22
+ @action = @action.with(@action.bindings.merge(object: @object))
23
+ @authorization_adapter&.attributes_for(:new, @abstract_model)&.each do |name, value|
24
+ @object.send("#{name}=", value)
25
+ end
26
+ object_params = params[@abstract_model.param_key]
27
+ if object_params
28
+ sanitize_params_for!(request.xhr? ? :modal : :create)
29
+ @object.assign_attributes(@object.attributes.merge(object_params.to_h))
30
+ end
31
+ respond_to do |format|
32
+ format.html { render @action.template_name }
33
+ format.js { render @action.template_name, layout: "rails_admin_next/modal", content_type: Mime[:html].to_s }
34
+ end
35
+
36
+ elsif request.post? # CREATE
37
+
38
+ @modified_assoc = []
39
+ @object = @abstract_model.new
40
+ sanitize_params_for!(request.xhr? ? :modal : :create)
41
+
42
+ @object.assign_attributes(params[@abstract_model.param_key])
43
+ @authorization_adapter&.authorize(:create, @abstract_model, @object)
44
+
45
+ if @object.save
46
+ @auditing_adapter&.create_object(@object, @abstract_model, _current_user)
47
+ respond_to do |format|
48
+ format.html { redirect_to_on_success }
49
+ format.json { render json: {id: @object.id.to_s, label: @model_config.with(object: @object).object_label} }
50
+ end
51
+ else
52
+ handle_save_error
53
+ end
54
+
55
+ end
56
+ end
57
+ end
58
+
59
+ register_instance_option :link_icon do
60
+ :new
61
+ end
62
+
63
+ register_instance_option :writable? do
64
+ !(bindings[:object] && bindings[:object].readonly?)
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,36 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class Show < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :member do
10
+ true
11
+ end
12
+
13
+ register_instance_option :route_fragment do
14
+ ""
15
+ end
16
+
17
+ register_instance_option :breadcrumb_parent do
18
+ [:index, bindings[:abstract_model]]
19
+ end
20
+
21
+ register_instance_option :controller do
22
+ proc do
23
+ respond_to do |format|
24
+ format.json { render json: @object }
25
+ format.html { render @action.template_name }
26
+ end
27
+ end
28
+ end
29
+
30
+ register_instance_option :link_icon do
31
+ :show
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class ShowInApp < RailsAdminNext::Config::Actions::Base
7
+ RailsAdminNext::Config::Actions.register(self)
8
+
9
+ register_instance_option :member do
10
+ true
11
+ end
12
+
13
+ register_instance_option :visible? do
14
+ authorized? && begin
15
+ bindings[:controller].main_app.url_for(bindings[:object])
16
+ rescue
17
+ false
18
+ end
19
+ end
20
+
21
+ register_instance_option :controller do
22
+ proc do
23
+ redirect_to main_app.url_for(@object)
24
+ end
25
+ end
26
+
27
+ register_instance_option :link_icon do
28
+ :show_in_app
29
+ end
30
+
31
+ register_instance_option :turbo? do
32
+ false
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,122 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RailsAdminNext
4
+ module Config
5
+ module Actions
6
+ class << self
7
+ def all(scope = nil, bindings = {})
8
+ if scope.is_a?(Hash)
9
+ bindings = scope
10
+ scope = :all
11
+ end
12
+ scope ||= :all
13
+ init_actions!
14
+ actions =
15
+ case scope
16
+ when :all
17
+ @@actions
18
+ when :root
19
+ @@actions.select(&:root?)
20
+ when :collection
21
+ @@actions.select(&:collection?)
22
+ when :bulkable
23
+ @@actions.select(&:bulkable?)
24
+ when :member
25
+ @@actions.select(&:member?)
26
+ end
27
+
28
+ actions = actions.collect { |action| action.with(bindings) }
29
+ bindings[:controller] ? actions.select(&:visible?) : actions
30
+ end
31
+
32
+ def find(custom_key, bindings = {})
33
+ init_actions!
34
+ action = @@actions.detect { |a| a.custom_key == custom_key }.try(:with, bindings)
35
+ bindings[:controller] ? (action.try(:visible?) && action || nil) : action
36
+ end
37
+
38
+ def collection(key, parent_class = :base, &)
39
+ add_action(key, parent_class, :collection, &)
40
+ end
41
+
42
+ def member(key, parent_class = :base, &)
43
+ add_action(key, parent_class, :member, &)
44
+ end
45
+
46
+ def root(key, parent_class = :base, &)
47
+ add_action(key, parent_class, :root, &)
48
+ end
49
+
50
+ def add_action(key, parent_class, parent, &)
51
+ a = "RailsAdminNext::Config::Actions::#{parent_class.to_s.camelize}".constantize.new
52
+ a.instance_eval(%(
53
+ #{parent} true
54
+ def key
55
+ :#{key}
56
+ end
57
+ ), __FILE__, __LINE__ - 5)
58
+ add_action_custom_key(a, &)
59
+ end
60
+
61
+ def reset
62
+ @@actions = nil
63
+ end
64
+
65
+ def register(name, klass = nil)
66
+ if klass.nil? && name.is_a?(Class)
67
+ klass = name
68
+ name = klass.to_s.demodulize.underscore.to_sym
69
+ end
70
+
71
+ instance_eval %{
72
+ def #{name}(&block)
73
+ action = #{klass}.new
74
+ add_action_custom_key(action, &block)
75
+ end
76
+ }, __FILE__, __LINE__ - 5
77
+ end
78
+
79
+ private
80
+
81
+ def init_actions!
82
+ @@actions ||= [
83
+ Dashboard.new,
84
+ Index.new,
85
+ Show.new,
86
+ New.new,
87
+ Edit.new,
88
+ Export.new,
89
+ Delete.new,
90
+ BulkDelete.new,
91
+ HistoryShow.new,
92
+ HistoryIndex.new,
93
+ ShowInApp.new
94
+ ]
95
+ end
96
+
97
+ def add_action_custom_key(action, &block)
98
+ action.instance_eval(&block) if block
99
+ @@actions ||= []
100
+ if action.custom_key.in?(@@actions.collect(&:custom_key))
101
+ raise "Action #{action.custom_key} already exists. Please change its custom key."
102
+ else
103
+ @@actions << action
104
+ end
105
+ end
106
+ end
107
+ end
108
+ end
109
+ end
110
+
111
+ require "rails_admin_next/config/actions/base"
112
+ require "rails_admin_next/config/actions/dashboard"
113
+ require "rails_admin_next/config/actions/index"
114
+ require "rails_admin_next/config/actions/show"
115
+ require "rails_admin_next/config/actions/show_in_app"
116
+ require "rails_admin_next/config/actions/history_show"
117
+ require "rails_admin_next/config/actions/history_index"
118
+ require "rails_admin_next/config/actions/new"
119
+ require "rails_admin_next/config/actions/edit"
120
+ require "rails_admin_next/config/actions/export"
121
+ require "rails_admin_next/config/actions/delete"
122
+ require "rails_admin_next/config/actions/bulk_delete"