cm-admin 0.9.0 → 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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/.github/ISSUE_TEMPLATE/bug_report.md +82 -0
  3. data/.github/ISSUE_TEMPLATE/config.yml +5 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +21 -0
  5. data/Gemfile.lock +96 -9
  6. data/app/assets/config/cm_admin_manifest.js +1 -0
  7. data/app/assets/javascripts/cm_admin/application.js +5 -0
  8. data/app/{javascript/packs → assets/javascripts}/cm_admin/exports.js +0 -0
  9. data/app/{javascript/packs → assets/javascripts}/cm_admin/filters.js +20 -31
  10. data/app/{javascript/packs → assets/javascripts}/cm_admin/form_validation.js +0 -0
  11. data/app/{javascript/packs → assets/javascripts}/cm_admin/quick_search.js +16 -3
  12. data/app/assets/javascripts/cm_admin/scaffolds.js +44 -0
  13. data/app/assets/stylesheets/cm_admin/base/form.scss +115 -40
  14. data/app/assets/stylesheets/cm_admin/base/scaffold.scss +2 -0
  15. data/app/assets/stylesheets/cm_admin/components/_input.scss +12 -0
  16. data/app/controllers/cm_admin/resource_controller.rb +10 -7
  17. data/app/helpers/cm_admin/application_helper.rb +0 -3
  18. data/app/javascript/packs/cm_admin/application.js +4 -4
  19. data/app/javascript/packs/cm_admin/scaffolds.js +81 -0
  20. data/app/views/cm_admin/main/_nested_fields.html.slim +26 -9
  21. data/app/views/cm_admin/main/_nested_table_form.html.slim +9 -10
  22. data/app/views/cm_admin/main/_tabs.html.slim +1 -1
  23. data/app/views/layouts/cm_admin.html.slim +9 -4
  24. data/app/views/layouts/static.html.slim +3 -2
  25. data/bin/importmap +15 -0
  26. data/bin/webpack +8 -8
  27. data/bin/webpack-dev-server +9 -9
  28. data/cm_admin.gemspec +3 -0
  29. data/config/importmap.rb +12 -0
  30. data/config/webpack/development.js +1 -1
  31. data/config/webpack/environment.js +1 -1
  32. data/config/webpack/production.js +1 -1
  33. data/config/webpacker.yml +2 -2
  34. data/lib/cm_admin/configuration.rb +5 -2
  35. data/lib/cm_admin/engine.rb +36 -15
  36. data/lib/cm_admin/models/filter.rb +1 -1
  37. data/lib/cm_admin/models/form_field.rb +8 -2
  38. data/lib/cm_admin/version.rb +1 -1
  39. data/lib/cm_admin/version_manager.rb +21 -0
  40. data/lib/cm_admin/view_helpers/form_field_helper.rb +183 -35
  41. data/lib/cm_admin/view_helpers/page_info_helper.rb +4 -0
  42. data/lib/cm_admin.rb +7 -2
  43. data/lib/generators/cm_admin/templates/actiontext.scss +0 -1
  44. data/lib/tasks/webpack_install.rake +15 -13
  45. data/package-lock.json +42 -55
  46. data/tmp/cache/webpacker/last-compilation-digest-development +1 -1
  47. data/yarn.lock +6708 -6916
  48. metadata +43 -6
@@ -106,12 +106,14 @@ module CmAdmin
106
106
  data = @action.parent == "index" ? @ar_object.data : @ar_object
107
107
  format.html { render @action.partial }
108
108
  else
109
- ar_object = @action.code_block.call(@ar_object)
110
- if ar_object.errors.empty?
111
- redirect_url = @model.current_action.redirection_url || @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@ar_object.id}"
109
+ response_object = @action.code_block.call(@response_object)
110
+ if response_object.class == Hash
111
+ format.json { render json: response_object }
112
+ elsif response_object.errors.empty?
113
+ redirect_url = @model.current_action.redirection_url || @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@response_object.id}"
112
114
  format.html { redirect_to redirect_url, notice: "#{@action.name.titleize} is successful" }
113
115
  else
114
- error_messages = ar_object.errors.full_messages.map{|error_message| "<li>#{error_message}</li>"}.join
116
+ error_messages = response_object.errors.full_messages.map{|error_message| "<li>#{error_message}</li>"}.join
115
117
  format.html { redirect_to request.referrer, alert: "<b>#{@action.name.titleize} is unsuccessful</b><br /><ul>#{error_messages}</ul>" }
116
118
  end
117
119
  end
@@ -193,9 +195,11 @@ module CmAdmin
193
195
  end
194
196
 
195
197
  def resource_params(params)
196
- columns = @model.ar_model.column_names
198
+ columns = @model.ar_model.columns_hash.map {|key, ar_adapter|
199
+ ar_adapter.sql_type_metadata.sql_type.ends_with?('[]') ? Hash[ar_adapter.name, []] : ar_adapter.name.to_sym
200
+ }
197
201
  columns += @model.ar_model.stored_attributes.values.flatten
198
- permittable_fields = @model.additional_permitted_fields + columns.reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym)
202
+ permittable_fields = @model.additional_permitted_fields + columns.reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }
199
203
  permittable_fields += @model.ar_model.name.constantize.reflect_on_all_associations.map {|x|
200
204
  next if x.options[:polymorphic]
201
205
  if x.class.name.include?('HasOne')
@@ -214,7 +218,6 @@ module CmAdmin
214
218
  }
215
219
  permittable_fields += nested_fields
216
220
  @model.ar_model.columns.map { |col| permittable_fields << col.name.split('_cents') if col.name.include?('_cents') }
217
-
218
221
  params.require(@model.name.underscore.to_sym).permit(*permittable_fields)
219
222
  end
220
223
 
@@ -1,8 +1,5 @@
1
- require "webpacker/helper"
2
-
3
1
  module CmAdmin
4
2
  module ApplicationHelper
5
- include ::Webpacker::Helper
6
3
 
7
4
  def current_webpacker_instance
8
5
  CmAdmin.webpacker
@@ -9,10 +9,10 @@ require('flatpickr')
9
9
  require("jgrowl")
10
10
  require("trix")
11
11
  require('./scaffolds.js')
12
- require('./form_validation.js')
13
- require('./quick_search.js')
14
- require('./filters.js')
15
- require('./exports.js')
12
+ require('/app/assets/javascripts/cm_admin/form_validation.js')
13
+ require('/app/assets/javascripts/cm_admin/quick_search.js')
14
+ require('/app/assets/javascripts/cm_admin/filters.js')
15
+ require('/app/assets/javascripts/cm_admin/exports.js')
16
16
 
17
17
  import jQuery from 'jquery'
18
18
  import LocalTime from "local-time"
@@ -74,3 +74,84 @@ $(document).on('click', '.drawer-close', function(e) {
74
74
  $('.cm-drawer').addClass('hidden');
75
75
  }, 300);
76
76
  });
77
+
78
+ $(document).on('change', '[data-field-type="linked-field"]', function(e) {
79
+ e.stopPropagation();
80
+ params = {}
81
+ params[$(this).data('field-name')] = $(this).val()
82
+ request_url = $(this).data('target-url') + '?' + $.param(params);
83
+ console.log(request_url)
84
+ $.ajax(request_url, {
85
+ type: 'GET',
86
+ success: function(data) {
87
+ apply_response_to_field(data)
88
+ },
89
+ error: function(jqxhr, textStatus, errorThrown) {
90
+ alert('Something went wrong. Please try again later.\n' + errorThrown);
91
+ }
92
+ });
93
+ });
94
+
95
+ function apply_response_to_field(response) {
96
+ $.each(response['fields'], function(key, value) {
97
+ switch(value['target_type']) {
98
+ case 'select':
99
+ update_options_in_select(value['target_value'])
100
+ break;
101
+ case 'input':
102
+ update_options_input_value(value['target_value'])
103
+ break;
104
+ case 'toggle_visibility':
105
+ toggle_field_visibility(value['target_value'])
106
+ }
107
+ })
108
+ }
109
+
110
+ function update_options_input_value(field_obj) {
111
+ input_tag = $('#' + field_obj['table'] + '_' + field_obj['field_name'])
112
+ input_tag.val(field_obj['field_value'])
113
+ }
114
+
115
+ function update_options_in_select(field_obj) {
116
+ select_tag = $('#' + field_obj['table'] + '_' + field_obj['field_name'])
117
+ select_tag.empty();
118
+ $.each(field_obj['field_value'], function(key, value) {
119
+ select_tag.append($("<option></option>")
120
+ .attr("value", value[1]).text(value[0]));
121
+ });
122
+ }
123
+
124
+ function toggle_field_visibility(field_obj) {
125
+ element = $('#' + field_obj['table'] + '_' + field_obj['field_name'])
126
+ element.closest('.input-wrapper').toggleClass('hidden')
127
+ }
128
+
129
+ $(document).on('cocoon:after-insert', '.nested-field-wrapper', function(e) {
130
+ e.stopPropagation();
131
+ replaceAccordionTitle($(this))
132
+ });
133
+
134
+ $(document).on('cocoon:after-remove', '.nested-field-wrapper', function(e) {
135
+ e.stopPropagation();
136
+ replaceAccordionTitle($(this))
137
+ });
138
+
139
+ $(document).ready( function () {
140
+ $('.nested-field-wrapper').each(function() {
141
+ replaceAccordionTitle($(this))
142
+ })
143
+ });
144
+
145
+ var replaceAccordionTitle = function(element) {
146
+ var i = 0;
147
+ var table_name = $(element).data('table-name')
148
+ var model_name = $(element).data('model-name')
149
+ $(element).find('.accordion-item:visible').each(function() {
150
+ i++;
151
+ var accordion_title = model_name + ' ' + i
152
+ var accordion_id = table_name + '-' + i
153
+ $(this).find('.accordion-button').text(accordion_title);
154
+ $(this).find('.accordion-button').attr('data-bs-target', '#' + accordion_id);
155
+ $(this).find('.accordion-collapse').attr('id', accordion_id);
156
+ });
157
+ }
@@ -1,9 +1,26 @@
1
- .nested-fields class=assoc_name
2
- - @model.available_fields[ action(action_name) ][assoc_name].each do |field|
3
- .row
4
- .col-sm-10
5
- = input_field_for_column(f, field)
6
- .col-sm-2
7
- - unless field.input_type == :hidden
8
- - if @reflections.select {|x| x if x.name == assoc_name}.first.macro == :has_many
9
- = link_to_remove_association "x", f
1
+ - fields = @model.available_fields[ action(action_name) ][assoc_name]
2
+ - if fields.count == 1
3
+ .nested-single-field.nested-fields
4
+ - fields.each do |field|
5
+ .field-input
6
+ = input_field_for_column(f, field)
7
+ .field-remove-action
8
+ - unless field.input_type == :hidden
9
+ - if @reflections.select {|x| x if x.name == assoc_name}.first.macro == :has_many
10
+ = link_to_remove_association "", f, class: 'fa fa-times'
11
+ - else
12
+ .accordion-item.nested-fields
13
+ h2#headingOne.accordion-header
14
+ button.accordion-button[type="button" data-bs-toggle="collapse" data-bs-target="##{assoc_name}-#{f.object.id}" aria-expanded="true" aria-controls="collapseOne"]
15
+ | Chapter 1
16
+ .field-remove-action
17
+ - if @reflections.select {|x| x if x.name == assoc_name}.first.macro == :has_many
18
+ = link_to_remove_association "", f, class: 'fa fa-trash ghost-btn accordion-delete-btn'
19
+ div.accordion-collapse.collapse.show[aria-labelledby="headingOne" id="#{assoc_name}-#{f.object.id}"]
20
+ .accordion-body
21
+ - fields.each do |field|
22
+ .form-field
23
+ .field-label-wrapper
24
+ label.field-label = field.field_name.to_s.titleize
25
+ .field-input-wrapper
26
+ = input_field_for_column(f, field)
@@ -1,10 +1,9 @@
1
- .nested-field-wrapper
2
- label.field-label = table_name.to_s.titleize
3
- - initialized_record_count = 1
4
- = f.fields_for table_name do |record|
5
- - if record.object.persisted? || initialized_record_count == 1
6
- = render partial: '/cm_admin/main/nested_fields', locals: { f: record, assoc_name: table_name }
7
- - initialized_record_count += 1 if record.object.new_record?
8
- - if @reflections.select {|x| x if x.name == table_name}.first.macro == :has_many
9
- .links
10
- = link_to_add_association "+ Add #{table_name.to_s.titleize}", f, table_name, partial: '/cm_admin/main/nested_fields', render_options: {locals: { assoc_name: table_name }}
1
+ .nested-field-wrapper data-table-name=table_name data-model-name=table_name.to_s.classify
2
+ label.nested-field-label = table_name.to_s.titleize
3
+ .accordion.nested-form-accordion
4
+ = f.fields_for table_name do |record|
5
+ - if record.object.persisted?
6
+ = render partial: '/cm_admin/main/nested_fields', locals: { f: record, assoc_name: table_name }
7
+ - if @reflections.select {|x| x if x.name == table_name}.first.macro == :has_many
8
+ .links
9
+ = link_to_add_association "+ Add #{table_name.to_s.titleize}", f, table_name, partial: '/cm_admin/main/nested_fields', render_options: {locals: { assoc_name: table_name }}, class: 'd-inline-block secondary-btn mt-2'
@@ -4,4 +4,4 @@ ul.nav.nav-pills
4
4
  - if nav_item.custom_action.empty? || (nav_item.custom_action.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{nav_item.custom_action}?"))
5
5
  li.nav-item
6
6
  - nav_item_action_name = nav_item.custom_action.present? ? nav_item.custom_action : 'show'
7
- = link_to nav_item.nav_item_name.to_s.titleize, cm_admin.send("#{@ar_object.model_name.singular}_#{nav_item_action_name}_path", @ar_object.id), class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"
7
+ = link_to tab_display_name(nav_item.nav_item_name), cm_admin.send("#{@ar_object.model_name.singular}_#{nav_item_action_name}_path", @ar_object.id), class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"
@@ -7,12 +7,17 @@ html
7
7
  = csrf_meta_tags
8
8
  = csp_meta_tag
9
9
  = stylesheet_link_tag 'cm_admin/cm_admin', media: 'all', 'data-turbolinks-track': 'reload'
10
- = stylesheet_pack_tag 'cm_admin/application', 'data-turbolinks-track': 'reload'
11
- link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" /
12
- = javascript_pack_tag 'cm_admin/application', 'data-turbolinks-track': 'reload'
10
+ - if CmAdmin::VersionManager.use_webpacker?
11
+ = stylesheet_pack_tag 'cm_admin/application', 'data-turbolinks-track': 'reload'
12
+ = javascript_pack_tag 'cm_admin/application', 'data-turbolinks-track': 'reload'
13
+ script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"
14
+ - elsif CmAdmin::VersionManager.use_importmap?
15
+ = javascript_importmap_tags
16
+ = javascript_import_module_tag "cm_admin/application"
13
17
  = javascript_include_tag 'cm_admin/custom', 'data-turbolinks-track': 'reload'
14
18
  = stylesheet_link_tag 'cm_admin/custom', media: 'all', 'data-turbolinks-track': 'reload'
15
- script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"
19
+ link href="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/css/select2.min.css" rel="stylesheet" /
20
+
16
21
  script src="https://raw.githack.com/SortableJS/Sortable/master/Sortable.js"
17
22
  body
18
23
  .cm-admin
@@ -7,8 +7,9 @@ html
7
7
  = csrf_meta_tags
8
8
  = csp_meta_tag
9
9
  = stylesheet_link_tag 'cm_admin/cm_admin', media: 'all', 'data-turbolinks-track': 'reload'
10
- = stylesheet_pack_tag 'cm_admin/application', 'data-turbolinks-track': 'reload'
11
- = javascript_pack_tag 'cm_admin/application', 'data-turbolinks-track': 'reload'
10
+ - if CmAdmin::VersionManager.rails6?
11
+ = stylesheet_pack_tag 'cm_admin/application', 'data-turbolinks-track': 'reload'
12
+ = javascript_pack_tag 'cm_admin/application', 'data-turbolinks-track': 'reload'
12
13
  body
13
14
  - flash.each do |type, msg|
14
15
  .alert class="alert-#{type}"
data/bin/importmap ADDED
@@ -0,0 +1,15 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ # NOTE: make sure we are loading the correct versions of things
4
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../Gemfile', __dir__)
5
+ require 'bundler/setup' if File.exist?(ENV['BUNDLE_GEMFILE'])
6
+
7
+ # NOTE: importmap requires some rails goodness that we don't have in the engine,
8
+ # because we don't have config/application.rb that loads the environment.
9
+ require 'rails'
10
+
11
+ # importmap-rails is not loaded automatically
12
+ require 'importmap-rails'
13
+
14
+ # the actual command runner
15
+ require 'importmap/commands'
data/bin/webpack CHANGED
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4
- ENV["NODE_ENV"] ||= "development"
3
+ ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development'
4
+ ENV['NODE_ENV'] ||= 'development'
5
5
 
6
- require "pathname"
7
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
6
+ require 'pathname'
7
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
8
8
  Pathname.new(__FILE__).realpath)
9
9
 
10
- require "bundler/setup"
10
+ require 'bundler/setup'
11
11
 
12
- require "webpacker"
13
- require "webpacker/webpack_runner"
12
+ require 'webpacker'
13
+ require 'webpacker/webpack_runner'
14
14
 
15
- APP_ROOT = File.expand_path("..", __dir__)
15
+ APP_ROOT = File.expand_path('..', __dir__)
16
16
  Dir.chdir(APP_ROOT) do
17
17
  Webpacker::WebpackRunner.run(ARGV)
18
18
  end
@@ -1,18 +1,18 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
- ENV["RAILS_ENV"] ||= ENV["RACK_ENV"] || "development"
4
- ENV["NODE_ENV"] ||= "development"
3
+ ENV['RAILS_ENV'] ||= ENV['RACK_ENV'] || 'development'
4
+ ENV['NODE_ENV'] ||= 'development'
5
5
 
6
- require "pathname"
7
- ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../Gemfile",
6
+ require 'pathname'
7
+ ENV['BUNDLE_GEMFILE'] ||= File.expand_path('../../Gemfile',
8
8
  Pathname.new(__FILE__).realpath)
9
9
 
10
- require "bundler/setup"
10
+ require 'bundler/setup'
11
11
 
12
- require "webpacker"
13
- require "webpacker/dev_server_runner"
12
+ require 'webpacker'
13
+ require 'webpacker/dev_server_runner'
14
14
 
15
- APP_ROOT = File.expand_path("..", __dir__)
15
+ APP_ROOT = File.expand_path('..', __dir__)
16
16
  Dir.chdir(APP_ROOT) do
17
17
  Webpacker::DevServerRunner.run(ARGV)
18
- end
18
+ end
data/cm_admin.gemspec CHANGED
@@ -26,6 +26,7 @@ Gem::Specification.new do |spec|
26
26
  spec.bindir = "exe"
27
27
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
28
28
  spec.require_paths = ["lib"]
29
+ spec.add_runtime_dependency('rails', '>= 6.0')
29
30
  spec.add_runtime_dependency 'caxlsx_rails'
30
31
  spec.add_runtime_dependency 'cocoon', '~> 1.2.15'
31
32
  spec.add_runtime_dependency 'local_time', '~> 2.1.0'
@@ -34,4 +35,6 @@ Gem::Specification.new do |spec|
34
35
  spec.add_runtime_dependency 'slim', '~> 4.1.0'
35
36
  spec.add_runtime_dependency 'webpacker', '~> 5.4.3'
36
37
  spec.add_runtime_dependency 'csv-importer', '~> 0.8.2'
38
+ spec.add_dependency 'importmap-rails'
39
+
37
40
  end
@@ -0,0 +1,12 @@
1
+ pin 'cm_admin/application'
2
+ pin 'jquery', to: 'https://ga.jspm.io/npm:jquery@3.6.0/dist/jquery.js', preload: true
3
+ pin 'bootstrap', to: 'https://ga.jspm.io/npm:bootstrap@5.1.3/dist/js/bootstrap.esm.js', preload: true
4
+ pin '@popperjs/core', to: 'https://ga.jspm.io/npm:@popperjs/core@2.11.5/lib/index.js', preload: true
5
+ pin 'flatpickr', to: 'https://ga.jspm.io/npm:flatpickr@4.6.13/dist/esm/index.js'
6
+ pin 'jgrowl', to: 'https://ga.jspm.io/npm:jgrowl@1.4.8/jquery.jgrowl.js'
7
+ pin 'moment', to: 'https://ga.jspm.io/npm:moment@2.29.4/moment.js'
8
+ pin 'trix', to: 'https://ga.jspm.io/npm:trix@2.0.0-beta.0/dist/trix.js'
9
+ pin '@fortawesome/fontawesome-free', to: 'https://ga.jspm.io/npm:@fortawesome/fontawesome-free@6.1.1/js/all.js'
10
+ pin 'daterangepicker', to: 'https://ga.jspm.io/npm:daterangepicker@3.1.0/daterangepicker.js'
11
+ pin '@nathanvda/cocoon', to: 'https://ga.jspm.io/npm:@nathanvda/cocoon@1.2.14/cocoon.js'
12
+ pin 'select2', to: 'https://ga.jspm.io/npm:select2@4.1.0-rc.0/dist/js/select2.js'
@@ -2,4 +2,4 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'development'
2
2
 
3
3
  const environment = require('./environment')
4
4
 
5
- module.exports = environment.toWebpackConfig()
5
+ module.exports = environment.toWebpackConfig()
@@ -10,4 +10,4 @@ environment.plugins.prepend('Provide',
10
10
  })
11
11
  )
12
12
 
13
- module.exports = environment
13
+ module.exports = environment
@@ -2,4 +2,4 @@ process.env.NODE_ENV = process.env.NODE_ENV || 'production'
2
2
 
3
3
  const environment = require('./environment')
4
4
 
5
- module.exports = environment.toWebpackConfig()
5
+ module.exports = environment.toWebpackConfig()
data/config/webpacker.yml CHANGED
@@ -10,7 +10,7 @@ default: &default
10
10
 
11
11
  # Additional paths webpack should lookup modules
12
12
  # ['app/assets', 'engine/foo/app/assets']
13
- additional_paths: []
13
+ additional_paths: ['app/assets']
14
14
 
15
15
  # Reload manifest.json on all requests so we reload latest compiled packs
16
16
  cache_manifest: false
@@ -89,4 +89,4 @@ production:
89
89
  extract_css: true
90
90
 
91
91
  # Cache manifest.json for performance
92
- cache_manifest: true
92
+ cache_manifest: true
@@ -1,10 +1,13 @@
1
1
  module CmAdmin
2
2
  class Configuration
3
- attr_accessor :layout, :included_models, :cm_admin_models
4
-
3
+ attr_accessor :layout, :included_models, :cm_admin_models, :authorized_roles
4
+
5
5
  def initialize
6
+ @layout = 'admin'
6
7
  @included_models = []
7
8
  @cm_admin_models = []
9
+ @authorized_roles = []
8
10
  end
11
+
9
12
  end
10
13
  end
@@ -1,4 +1,7 @@
1
1
  require 'rails'
2
+ require 'importmap-rails'
3
+ require 'cm_admin/version_manager'
4
+
2
5
  module CmAdmin
3
6
  class Engine < Rails::Engine
4
7
  isolate_namespace CmAdmin
@@ -17,24 +20,42 @@ module CmAdmin
17
20
  )
18
21
  end
19
22
 
20
- initializer "webpacker.proxy" do |app|
21
- insert_middleware = begin
22
- CmAdmin.webpacker.config.dev_server.present?
23
- rescue
24
- nil
25
- end
26
- next unless insert_middleware
27
-
28
- app.middleware.insert_before(
29
- 0, Webpacker::DevServerProxy, # "Webpacker::DevServerProxy" if Rails version < 5
30
- ssl_verify_none: true,
31
- webpacker: CmAdmin.webpacker
32
- )
33
- end
34
-
35
23
  def mount_path
36
24
  CmAdmin::Engine.routes.find_script_name({})
37
25
  end
38
26
 
27
+ if VersionManager.rails6?
28
+ initializer "webpacker.proxy" do |app|
29
+ insert_middleware = begin
30
+ CmAdmin.webpacker.config.dev_server.present?
31
+ rescue
32
+ nil
33
+ end
34
+ next unless insert_middleware
35
+
36
+ app.middleware.insert_before(
37
+ 0, Webpacker::DevServerProxy, # "Webpacker::DevServerProxy" if Rails version < 5
38
+ ssl_verify_none: true,
39
+ webpacker: CmAdmin.webpacker
40
+ )
41
+ end
42
+ elsif VersionManager.rails7?
43
+ initializer "cm_admin.importmap", before: "importmap" do |app|
44
+ # NOTE: this will add pins from this engine to the main app
45
+ # https://github.com/rails/importmap-rails#composing-import-maps
46
+ app.config.importmap.paths << root.join("config/importmap.rb")
47
+
48
+ # NOTE: something about cache; I did not look into it.
49
+ # https://github.com/rails/importmap-rails#sweeping-the-cache-in-development-and-test
50
+ app.config.importmap.cache_sweepers << root.join("app/assets/javascripts")
51
+ end
52
+
53
+ # NOTE: add engine manifest to precompile assets in production
54
+ initializer "cm_admin.assets" do |app|
55
+ app.config.assets.precompile += %w[cm_admin_manifest]
56
+ end
57
+ end
58
+
59
+
39
60
  end
40
61
  end
@@ -70,7 +70,7 @@ module CmAdmin
70
70
 
71
71
  if filter.db_column_name.map{|x| x.is_a?(Hash)}.include?(true)
72
72
  associations_hash = filter.db_column_name.select{|x| x if x.is_a?(Hash)}.last
73
- records = records.joins(associations_hash.keys)
73
+ records = records.left_joins(associations_hash.keys).distinct
74
74
  end
75
75
 
76
76
  records = records.where(
@@ -1,8 +1,13 @@
1
1
  module CmAdmin
2
2
  module Models
3
3
  class FormField
4
- attr_accessor :field_name, :label, :header, :input_type, :collection, :disabled, :helper_method, :placeholder, :display_if, :html_attr
5
- VALID_INPUT_TYPES = [:integer, :decimal, :string, :single_select, :multi_select, :date, :date_time, :text, :single_file_upload, :multi_file_upload, :hidden, :rich_text].freeze
4
+ attr_accessor :field_name, :label, :header, :input_type, :collection, :disabled, :helper_method,
5
+ :placeholder, :display_if, :html_attr, :target
6
+
7
+ VALID_INPUT_TYPES = %i[
8
+ integer decimal string single_select multi_select date date_time text
9
+ single_file_upload multi_file_upload hidden rich_text check_box radio_button
10
+ ].freeze
6
11
 
7
12
  def initialize(field_name, input_type, attributes = {})
8
13
  @field_name = field_name
@@ -20,6 +25,7 @@ module CmAdmin
20
25
  self.input_type = :string
21
26
  self.placeholder = "Enter #{self.field_name.to_s.downcase.gsub('_', ' ')}"
22
27
  self.html_attr = {}
28
+ self.target = {}
23
29
  end
24
30
  end
25
31
  end
@@ -1,3 +1,3 @@
1
1
  module CmAdmin
2
- VERSION = '0.9.0'
2
+ VERSION = '1.0.0'
3
3
  end
@@ -0,0 +1,21 @@
1
+ module CmAdmin
2
+ class VersionManager
3
+ class << self
4
+ def rails6?
5
+ Rails::VERSION::MAJOR == 6
6
+ end
7
+
8
+ def rails7?
9
+ Rails::VERSION::MAJOR == 7
10
+ end
11
+
12
+ def use_importmap?
13
+ rails7? && File.exist?('config/importmap.rb')
14
+ end
15
+
16
+ def use_webpacker?
17
+ rails6? && defined?(Webpacker) == 'constant'
18
+ end
19
+ end
20
+ end
21
+ end