cm-admin 0.5.6 → 0.5.9

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 (37) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +1 -0
  3. data/Gemfile.lock +29 -23
  4. data/README.md +5 -1
  5. data/app/assets/stylesheets/cm_admin/base/scaffold.scss +21 -0
  6. data/app/assets/stylesheets/cm_admin/components/_drawer.scss +7 -1
  7. data/app/assets/stylesheets/cm_admin/scaffold.scss +12 -6
  8. data/app/controllers/cm_admin/application_controller.rb +3 -0
  9. data/app/policies/application_policy.rb +53 -0
  10. data/app/views/cm_admin/main/_associated_table.html.slim +2 -2
  11. data/app/views/cm_admin/main/_table.html.slim +19 -15
  12. data/app/views/cm_admin/main/_tabs.html.slim +4 -3
  13. data/app/views/cm_admin/main/_top_navbar.html.slim +4 -5
  14. data/app/views/cm_admin/main/associated_index.html.slim +1 -1
  15. data/app/views/cm_admin/main/index.html.slim +5 -2
  16. data/app/views/cm_admin/static/dashboard.html.slim +1 -0
  17. data/app/views/cm_admin/static/error_403.html.slim +4 -0
  18. data/cm_admin.gemspec +1 -0
  19. data/config/initializers/active_record_extension.rb +1 -1
  20. data/config/routes.rb +1 -1
  21. data/lib/cm_admin/configuration.rb +10 -0
  22. data/lib/cm_admin/model.rb +39 -4
  23. data/lib/cm_admin/models/action.rb +9 -1
  24. data/lib/cm_admin/models/controller_method.rb +3 -3
  25. data/lib/cm_admin/models/dsl_method.rb +13 -14
  26. data/lib/cm_admin/models/field.rb +2 -1
  27. data/lib/cm_admin/version.rb +1 -1
  28. data/lib/cm_admin/view_helpers/field_display_helper.rb +16 -7
  29. data/lib/cm_admin/view_helpers/form_helper.rb +7 -5
  30. data/lib/cm_admin/view_helpers/navigation_helper.rb +19 -17
  31. data/lib/cm_admin/view_helpers/page_info_helper.rb +0 -4
  32. data/lib/cm_admin.rb +13 -7
  33. data/lib/generators/cm_admin/install_generator.rb +11 -21
  34. data/lib/generators/cm_admin/templates/cm_admin_initializer.rb +4 -0
  35. data/lib/generators/cm_admin/templates/custom.css +0 -0
  36. data/lib/generators/cm_admin/templates/custom.js +0 -0
  37. metadata +27 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9e71407dad6f3a42e093faa7247489382dd4b650b3c61f85b6758286a7d2ee45
4
- data.tar.gz: e50e11e94676d06e9044a58b84f20cb416d92e8a0a92507afa5ff362b98d9640
3
+ metadata.gz: b0f2b3549e1dfc742d740ac99368efcd98d19fb70f490581568816a2eb88d238
4
+ data.tar.gz: 515da90e85fdf498116babe7798decc32453d2667d95e9dc0eb74e1ab89c64db
5
5
  SHA512:
6
- metadata.gz: 07bf22fe0ea5157252da7a3b17b012f6842ce5da4815764fd6ace17af0203db2dd09158d97efc9f19c51e9df5529f742c7284e501b5879b3694e48aed4283cf3
7
- data.tar.gz: 9433f9fd8d71db8f7d1a95668e723cf655cc91e66df19b73d73f405336a7649e8c2a1f011c901a898990512a1e4eefe5092ed7f6502feabf75599a2e0ac0ff1d
6
+ metadata.gz: 8630a7ce57b1b00ca9497d2f4209ee8d86df18304a44f5fbf6ee85c8f70eda19bd9d415abc4502793eeee9f93aa5d4c83630555ae46b1e456fffa45cd0e3d922
7
+ data.tar.gz: 50c02b1132b2382e4adbdde2799c7f3104de07f95a421dbbe371e546424a62c3a000c4a487c494300f9bf5dc36ad7ec317cbeb2d0187802c565f1fac23321900
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ gem 'slim'
5
5
  gem "rake", "~> 12.0"
6
6
  gem "rspec", "~> 3.0"
7
7
  gem 'cocoon'
8
+ gem 'pundit'
8
9
 
9
10
  # Specify your gem's dependencies in cm_admin.gemspec
10
11
  gemspec
data/Gemfile.lock CHANGED
@@ -1,40 +1,40 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- cm-admin (0.4.2)
4
+ cm-admin (0.5.7)
5
5
  axlsx_rails (~> 0.6.1)
6
6
  cocoon (~> 1.2.15)
7
7
  pagy (~> 4.11.0)
8
+ pundit (~> 2.2.0)
8
9
  slim (~> 4.1.0)
9
10
  webpacker (~> 5.2.1)
10
11
 
11
12
  GEM
12
13
  remote: https://rubygems.org/
13
14
  specs:
14
- actionpack (6.1.4.1)
15
- actionview (= 6.1.4.1)
16
- activesupport (= 6.1.4.1)
17
- rack (~> 2.0, >= 2.0.9)
15
+ actionpack (7.0.2.3)
16
+ actionview (= 7.0.2.3)
17
+ activesupport (= 7.0.2.3)
18
+ rack (~> 2.0, >= 2.2.0)
18
19
  rack-test (>= 0.6.3)
19
20
  rails-dom-testing (~> 2.0)
20
21
  rails-html-sanitizer (~> 1.0, >= 1.2.0)
21
- actionview (6.1.4.1)
22
- activesupport (= 6.1.4.1)
22
+ actionview (7.0.2.3)
23
+ activesupport (= 7.0.2.3)
23
24
  builder (~> 3.1)
24
25
  erubi (~> 1.4)
25
26
  rails-dom-testing (~> 2.0)
26
27
  rails-html-sanitizer (~> 1.1, >= 1.2.0)
27
- activesupport (6.1.4.1)
28
+ activesupport (7.0.2.3)
28
29
  concurrent-ruby (~> 1.0, >= 1.0.2)
29
30
  i18n (>= 1.6, < 2)
30
31
  minitest (>= 5.1)
31
32
  tzinfo (~> 2.0)
32
- zeitwerk (~> 2.3)
33
33
  axlsx_rails (0.6.1)
34
34
  actionpack (>= 3.1)
35
35
  caxlsx (>= 3.0)
36
36
  builder (3.2.4)
37
- caxlsx (3.1.1)
37
+ caxlsx (3.2.0)
38
38
  htmlentities (~> 4.3, >= 4.3.4)
39
39
  marcel (~> 1.0)
40
40
  nokogiri (~> 1.10, >= 1.10.4)
@@ -45,20 +45,24 @@ GEM
45
45
  diff-lcs (1.4.4)
46
46
  erubi (1.10.0)
47
47
  htmlentities (4.3.4)
48
- i18n (1.8.10)
48
+ i18n (1.10.0)
49
49
  concurrent-ruby (~> 1.0)
50
- loofah (2.12.0)
50
+ loofah (2.15.0)
51
51
  crass (~> 1.0.2)
52
52
  nokogiri (>= 1.5.9)
53
53
  marcel (1.0.2)
54
54
  method_source (1.0.0)
55
- minitest (5.14.4)
56
- nokogiri (1.12.5-x86_64-darwin)
55
+ mini_portile2 (2.8.0)
56
+ minitest (5.15.0)
57
+ nokogiri (1.13.3)
58
+ mini_portile2 (~> 2.8.0)
57
59
  racc (~> 1.4)
58
60
  pagy (4.11.0)
59
- racc (1.5.2)
61
+ pundit (2.2.0)
62
+ activesupport (>= 3.0.0)
63
+ racc (1.6.0)
60
64
  rack (2.2.3)
61
- rack-proxy (0.7.0)
65
+ rack-proxy (0.7.2)
62
66
  rack
63
67
  rack-test (1.1.0)
64
68
  rack (>= 1.0, < 3)
@@ -67,12 +71,13 @@ GEM
67
71
  nokogiri (>= 1.6)
68
72
  rails-html-sanitizer (1.4.2)
69
73
  loofah (~> 2.3)
70
- railties (6.1.4.1)
71
- actionpack (= 6.1.4.1)
72
- activesupport (= 6.1.4.1)
74
+ railties (7.0.2.3)
75
+ actionpack (= 7.0.2.3)
76
+ activesupport (= 7.0.2.3)
73
77
  method_source
74
- rake (>= 0.13)
78
+ rake (>= 12.2)
75
79
  thor (~> 1.0)
80
+ zeitwerk (~> 2.5)
76
81
  rake (12.3.3)
77
82
  rspec (3.10.0)
78
83
  rspec-core (~> 3.10.0)
@@ -93,7 +98,7 @@ GEM
93
98
  temple (>= 0.7.6, < 0.9)
94
99
  tilt (>= 2.0.6, < 2.1)
95
100
  temple (0.8.2)
96
- thor (1.1.0)
101
+ thor (1.2.1)
97
102
  tilt (2.0.10)
98
103
  tzinfo (2.0.4)
99
104
  concurrent-ruby (~> 1.0)
@@ -102,7 +107,7 @@ GEM
102
107
  rack-proxy (>= 0.6.1)
103
108
  railties (>= 5.2)
104
109
  semantic_range (>= 2.3.0)
105
- zeitwerk (2.4.2)
110
+ zeitwerk (2.5.4)
106
111
 
107
112
  PLATFORMS
108
113
  ruby
@@ -111,9 +116,10 @@ DEPENDENCIES
111
116
  cm-admin!
112
117
  cocoon
113
118
  pagy (~> 4.11.0)
119
+ pundit
114
120
  rake (~> 12.0)
115
121
  rspec (~> 3.0)
116
122
  slim
117
123
 
118
124
  BUNDLED WITH
119
- 2.0.2
125
+ 2.2.33
data/README.md CHANGED
@@ -24,7 +24,11 @@ Install the gem
24
24
 
25
25
  $ rails g cm_admin:install
26
26
 
27
- ## Usage
27
+ ## Documentation
28
+
29
+ You can find more detailed documentation [here](https://github.com/commutatus/cm-admin/wiki)
30
+
31
+ ## Demo
28
32
 
29
33
  For demo check [here](http://cm-admin.labs.commutatus.com/admin/users/)
30
34
 
@@ -79,6 +79,27 @@ a {
79
79
  overflow: auto;
80
80
  }
81
81
 
82
+ .input-wrapper {
83
+ margin-bottom: 24px;
84
+ input, select, .select2 {
85
+ width: 320px;
86
+ }
87
+ textarea {
88
+ width: 480px;
89
+ }
90
+ }
91
+ .input-wrapper.disabled {
92
+ input:disabled {
93
+ background-color: $grey-lightest-clr;
94
+ }
95
+ label {
96
+ color: $ink-lightest-clr;
97
+ }
98
+ }
99
+ .nested-fields .select2 {
100
+ width: 320px !important;
101
+ }
102
+
82
103
  .datetime-wrapper {
83
104
  position: relative;
84
105
  }
@@ -83,4 +83,10 @@
83
83
  left: -400px;
84
84
  opacity: 0;
85
85
  }
86
- }
86
+ }
87
+
88
+ .drawer-btn {
89
+ cursor: pointer;
90
+ margin-left: 8px;
91
+ @include font($size: $t4-text, $color: $brand-color);
92
+ }
@@ -1,16 +1,18 @@
1
+ @import "helpers/index.scss";
2
+
1
3
  .jGrowl {
2
- color: #1D2129 !important;
4
+ color: $ink-regular-clr !important;
3
5
  font-size: 14px !important;
4
6
  .success{
5
- background-color: #C1EDE2 !important;
7
+ background-color: $green-light-clr !important;
6
8
  }
7
9
  .notice {
8
- background-color: #CDE1FB !important;
10
+ background-color: $blue-light-clr !important;
9
11
  }
10
12
  .error {
11
- background-color: #FDCFCF !important;
13
+ background-color: $red-light-clr !important;
12
14
  }
13
-
15
+
14
16
  }
15
17
 
16
18
  .nested-field-wrapper {
@@ -21,4 +23,8 @@
21
23
  .nested-fields {
22
24
  margin-bottom: 16px;
23
25
  }
24
- }
26
+ }
27
+
28
+ .ink-light-clr {
29
+ color: $ink-lighter-clr;
30
+ }
@@ -1,11 +1,14 @@
1
1
  module CmAdmin
2
2
  class ApplicationController < ::ActionController::Base
3
+ include Pundit::Authorization
3
4
  # before_action :check_cm_admin
4
5
  layout 'cm_admin'
5
6
  helper CmAdmin::ViewHelpers
6
7
 
8
+
7
9
  def check_cm_admin
8
10
  redirect_to CmAdmin::Engine.mount_path + '/access-denied' unless defined?(::Current) && ::Current.cm_admin_user
9
11
  end
12
+
10
13
  end
11
14
  end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ApplicationPolicy
4
+ attr_reader :user, :record
5
+
6
+ def initialize(user, record)
7
+ @user = user
8
+ @record = record
9
+ end
10
+
11
+ def index?
12
+ false
13
+ end
14
+
15
+ def show?
16
+ true
17
+ end
18
+
19
+ def create?
20
+ false
21
+ end
22
+
23
+ def new?
24
+ create?
25
+ end
26
+
27
+ def update?
28
+ false
29
+ end
30
+
31
+ def edit?
32
+ update?
33
+ end
34
+
35
+ def destroy?
36
+ false
37
+ end
38
+
39
+ class Scope
40
+ def initialize(user, scope)
41
+ @user = user
42
+ @scope = scope
43
+ end
44
+
45
+ def resolve
46
+ raise NotImplementedError, "You must define #resolve in #{self.class}"
47
+ end
48
+
49
+ private
50
+
51
+ attr_reader :user, :scope
52
+ end
53
+ end
@@ -1,6 +1,6 @@
1
1
  .admin-table-index
2
2
  .table-top
3
- p.table-top__total-count = "#{@associated_ar_object.pagy.count} #{@associated_model&.ar_model&.table_name} found"
3
+ p.table-top__total-count = "#{@associated_ar_object.pagy.count} #{@action.child_records.to_s.gsub('_', ' ')} found"
4
4
  .table-top__column-action
5
5
  button.secondary-btn.column-btn data-target="#columnActionModal" data-toggle="modal" type="button"
6
6
  span
@@ -51,7 +51,7 @@
51
51
  == render partial: 'cm_admin/main/cm_pagy_nav', locals: { pagy: @associated_ar_object.pagy }
52
52
 
53
53
  - @associated_ar_object.data.each do |ar_object|
54
- - @associated_model && @associated_model.available_actions.select{|act| act if act.route_type == 'member'}.each do |custom_action|
54
+ - @associated_model && @associated_model.available_actions.select{|act| act if (act.route_type == 'member' && act.display_type == :modal)}.each do |custom_action|
55
55
  .modal.fade id="#{custom_action.name.classify}Modal-#{ar_object.id.to_s}" aria-hidden="true" aria-labelledby="#{custom_action.name.classify}ModalLabel" tabindex="1"
56
56
  .modal-dialog
57
57
  .modal-content
@@ -31,21 +31,25 @@
31
31
  = show_field_value(ar_object, column)
32
32
  - if column.field_type == :drawer
33
33
  = render partial: column.drawer_partial, locals: { ar_object: ar_object}
34
- td.row-action-cell
35
- .row-action-tool
36
- button.secondary-btn.tool-btn type="button"
37
- span
38
- i.fa.fa-bars.bolder
39
- span
40
- i.fa.fa-angle-down
41
- .popup-card.table-export-popup.hidden
42
- .popup-option
43
- a href="#{page_url('edit', ar_object)}"
44
- | Edit
45
- - @model.available_actions.select{|act| act if act.route_type == 'member' && [:button, :modal].include?(act.display_type)}.each do |custom_action|
46
- - if custom_action.display_if.call(ar_object)
47
- .popup-option
48
- = link_to custom_action.name.titleize, custom_action.path.gsub(':id', ar_object.id.to_s), method: custom_action.verb
34
+
35
+ - edit_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('edit')}
36
+ - custom_actions = @model.available_actions.select{|act| act if act.route_type == 'member' && [:button, :modal].include?(act.display_type)}
37
+ - if custom_actions.any? || edit_action.any?
38
+ td.row-action-cell
39
+ .row-action-tool
40
+ button.secondary-btn.tool-btn type="button"
41
+ span
42
+ i.fa.fa-bars.bolder
43
+ span
44
+ i.fa.fa-angle-down
45
+ .popup-card.table-export-popup.hidden
46
+ - if edit_action.any?
47
+ = link_to "#{page_url('edit', ar_object)}" do
48
+ .popup-option Edit
49
+ - custom_actions.each do |custom_action|
50
+ - if custom_action.display_if.call(ar_object)
51
+ = link_to custom_action.path.gsub(':id', ar_object.id.to_s), method: custom_action.verb do
52
+ .popup-option = custom_action.name.titleize
49
53
 
50
54
  .cm-pagination
51
55
  .cm-pagination__lhs Showing #{@ar_object.pagy.from} to #{@ar_object.pagy.to} out of #{@ar_object.pagy.count}
@@ -1,5 +1,6 @@
1
1
  ul.nav.nav-pills
2
2
  - @model.available_tabs.each do |nav_item|
3
- li.nav-item
4
- - nav_item_action_name = nav_item.custom_action.present? ? nav_item.custom_action : 'show'
5
- = link_to nav_item.nav_item_name.to_s.titleize, "/cm_admin/#{@model.name.underscore.pluralize}/#{@ar_object.id}/#{nav_item.custom_action}", class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"
3
+ - if nav_item.custom_action.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{nav_item.custom_action}?")
4
+ li.nav-item
5
+ - nav_item_action_name = nav_item.custom_action.present? ? nav_item.custom_action : 'show'
6
+ = link_to nav_item.nav_item_name.to_s.titleize, "/cm_admin/#{@model.name.underscore.pluralize}/#{@ar_object.id}/#{nav_item.custom_action}", class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"
@@ -20,9 +20,9 @@
20
20
  li
21
21
  .popup-option.pointer data-bs-toggle='modal' data-bs-target='#exportmodal'
22
22
  span Export
23
-
24
- a.primary-btn.ml-2 href="#{page_url('new')}"
25
- | Add
23
+ - new_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('new')}
24
+ - if new_action.any?
25
+ = link_to 'Add', "#{page_url('new')}", class: 'primary-btn ml-2'
26
26
  - @model.available_actions.select{|act| act if act.route_type == 'collection'}.each do |custom_action|
27
27
  - if custom_action.display_type == :button
28
28
  = link_to custom_action.name.titleize, @model.ar_model.table_name + '/' + custom_action.path, class: 'primary-btn ml-2', method: custom_action.verb
@@ -37,5 +37,4 @@
37
37
 
38
38
  - edit_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('edit')}
39
39
  - if edit_action.any?
40
- a.primary-btn.ml-2 href="#{page_url('edit', @ar_object)}"
41
- = "Edit #{@model.name}"
40
+ = link_to "Edit #{@model.name}", "#{page_url('edit', @ar_object)}", class: 'primary-btn ml-2'
@@ -1,6 +1,6 @@
1
1
  .cm-index-page
2
2
  .index-page
3
- .index-page__table-container.pt-0
3
+ .index-page__table-container
4
4
  == render partial: 'cm_admin/main/associated_table'
5
5
 
6
6
  // = column_pop_up(@associated_model)
@@ -2,11 +2,14 @@
2
2
  .index-page.page-container
3
3
  .sticky-container
4
4
  == render 'cm_admin/main/top_navbar'
5
- - if @model.filters.present?
5
+ - if @model.filters.present? && @action.partial.nil?
6
6
  .index-page__filters
7
7
  == render partial: 'cm_admin/main/filters', locals: { filters: @model.filters }
8
8
  .index-page__table-container
9
- == render 'cm_admin/main/table'
9
+ - if @action.partial
10
+ == render @action.partial
11
+ - else
12
+ == render 'cm_admin/main/table'
10
13
 
11
14
  = column_pop_up(@model)
12
15
  = manage_column_pop_up(@model)
@@ -0,0 +1 @@
1
+ | Dashboard section
@@ -0,0 +1,4 @@
1
+ main.flex-shrink-0
2
+ .container
3
+ h1.mt-5 403
4
+ p.lead You do not have permission to access this page.
data/cm_admin.gemspec CHANGED
@@ -31,4 +31,5 @@ Gem::Specification.new do |spec|
31
31
  spec.add_runtime_dependency 'webpacker', '~> 5.2.1'
32
32
  spec.add_runtime_dependency 'axlsx_rails', '~> 0.6.1'
33
33
  spec.add_runtime_dependency 'cocoon', '~> 1.2.15'
34
+ spec.add_runtime_dependency 'pundit', '~> 2.2.0'
34
35
  end
@@ -2,7 +2,7 @@ ActiveSupport.on_load(:active_record) do
2
2
  module ActiveRecord
3
3
  class Base
4
4
  def self.cm_admin(&block)
5
- CmAdmin.config(self, &block)
5
+ CmAdmin.initialize_model(self, &block)
6
6
  end
7
7
  end
8
8
  end
data/config/routes.rb CHANGED
@@ -9,7 +9,7 @@ CmAdmin::Engine.routes.draw do
9
9
  end
10
10
 
11
11
  # Defining action routes for each model
12
- CmAdmin.cm_admin_models.each do |model|
12
+ CmAdmin.config.cm_admin_models.each do |model|
13
13
  model.available_actions.sort_by {|act| act.class}.each do |act|
14
14
  scope model.name.tableize do
15
15
  send(act.verb, act.path.present? ? act.path : act.name, to: "#{model.name.underscore}##{act.name}", as: "#{model.name.underscore}_#{act.name}")
@@ -0,0 +1,10 @@
1
+ module CmAdmin
2
+ class Configuration
3
+ attr_accessor :layout, :included_models, :cm_admin_models
4
+
5
+ def initialize
6
+ @included_models = []
7
+ @cm_admin_models = []
8
+ end
9
+ end
10
+ end
@@ -14,6 +14,7 @@ require_relative 'models/controller_method'
14
14
  require 'pagy'
15
15
  require 'axlsx'
16
16
  require 'cocoon'
17
+ require 'pundit'
17
18
 
18
19
  module CmAdmin
19
20
  class Model
@@ -21,7 +22,8 @@ module CmAdmin
21
22
  include Models::Blocks
22
23
  include Models::DslMethod
23
24
  include Models::ControllerMethod
24
- attr_accessor :available_actions, :actions_set, :available_fields, :permitted_fields, :current_action, :params, :filters, :available_tabs
25
+ attr_accessor :available_actions, :actions_set, :available_fields, :permitted_fields,
26
+ :current_action, :params, :filters, :available_tabs, :icon_name
25
27
  attr_reader :name, :ar_model, :is_visible_on_sidebar
26
28
 
27
29
  # Class variable for storing all actions
@@ -32,6 +34,7 @@ module CmAdmin
32
34
  @name = entity.name
33
35
  @ar_model = entity
34
36
  @is_visible_on_sidebar = true
37
+ @icon_name = 'fa fa-th-large'
35
38
  @available_actions ||= []
36
39
  @current_action = nil
37
40
  @available_tabs ||= []
@@ -42,6 +45,7 @@ module CmAdmin
42
45
  actions unless @actions_set
43
46
  $available_actions = @available_actions.dup
44
47
  self.class.all_actions.push(@available_actions)
48
+ define_policy
45
49
  define_controller
46
50
  end
47
51
 
@@ -51,7 +55,7 @@ module CmAdmin
51
55
  end
52
56
 
53
57
  def find_by(search_hash)
54
- CmAdmin.cm_admin_models.find { |x| x.name == search_hash[:name] }
58
+ CmAdmin.config.cm_admin_models.find { |x| x.name == search_hash[:name] }
55
59
  end
56
60
  end
57
61
 
@@ -59,7 +63,7 @@ module CmAdmin
59
63
  current_action = CmAdmin::Models::Action.find_by(self, name: action_name.to_s)
60
64
  if current_action
61
65
  @current_action = current_action
62
- @ar_object = @ar_model.find(params[:id])
66
+ @ar_object = @ar_model.name.classify.constantize.find(params[:id])
63
67
  if @current_action.child_records
64
68
  child_records = @ar_object.send(@current_action.child_records)
65
69
  @associated_model = CmAdmin::Model.find_by(name: @ar_model.reflect_on_association(@current_action.child_records).klass.name)
@@ -90,13 +94,37 @@ module CmAdmin
90
94
  @is_visible_on_sidebar = visible_option
91
95
  end
92
96
 
97
+ def set_icon(name)
98
+ @icon_name = name
99
+ end
100
+
93
101
 
94
102
  private
95
103
 
104
+ def define_policy
105
+ klass = Class.new(ApplicationPolicy) do
106
+ def initialize(user, record)
107
+ @user = user
108
+ @record = record
109
+ end
110
+
111
+ $available_actions.each do |action|
112
+ define_method :"#{action.name}?" do
113
+ accessible_by = action.accessible_by.map { |role| "user.#{role}" }.join(' || ')
114
+ eval(accessible_by)
115
+ end
116
+ end
117
+ end
118
+ CmAdmin.const_set "#{@name}Policy", klass
119
+ end
120
+
96
121
  # Controller defined for each model
97
122
  # If model is User, controller will be UsersController
98
123
  def define_controller
99
124
  klass = Class.new(CmAdmin::ApplicationController) do
125
+ include Pundit::Authorization
126
+ rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
127
+
100
128
  $available_actions.each do |action|
101
129
  define_method action.name.to_sym do
102
130
 
@@ -107,6 +135,7 @@ module CmAdmin
107
135
  @model.current_action = @action
108
136
  @ar_object = @model.try(@action.parent || action_name, params)
109
137
  @ar_object, @associated_model, @associated_ar_object = @model.custom_controller_action(action_name, params.permit!) if !@ar_object.present? && params[:id].present?
138
+ authorize controller_name.classify.constantize, policy_class: "CmAdmin::#{controller_name.classify}Policy".constantize
110
139
  aar_model = request.url.split('/')[-2].classify.constantize if params[:aar_id]
111
140
  @associated_ar_object = aar_model.find(params[:aar_id]) if params[:aar_id]
112
141
  nested_tables = @model.available_fields[:new].except(:fields).keys
@@ -141,7 +170,7 @@ module CmAdmin
141
170
  format.html { render action.partial }
142
171
  else
143
172
  if @action.code_block.call(@ar_object)
144
- redirect_url = @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@ar_object.id}"
173
+ redirect_url = @model.current_action.redirection_url || @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@ar_object.id}"
145
174
  format.html { redirect_to redirect_url }
146
175
  else
147
176
  format.html { redirect_to request.referrer }
@@ -157,6 +186,12 @@ module CmAdmin
157
186
  end
158
187
  end
159
188
  end
189
+ private
190
+
191
+ def user_not_authorized
192
+ flash[:alert] = 'You are not authorized to perform this action.'
193
+ redirect_to CmAdmin::Engine.mount_path + '/access-denied'
194
+ end
160
195
  end if $available_actions.present?
161
196
  CmAdmin.const_set "#{@name}Controller", klass
162
197
  end
@@ -6,7 +6,7 @@ module CmAdmin
6
6
  include Actions::Blocks
7
7
  attr_accessor :name, :verb, :layout_type, :layout, :partial, :path, :page_title, :page_description,
8
8
  :child_records, :is_nested_field, :nested_table_name, :parent, :display_if, :route_type, :code_block,
9
- :display_type, :action_type, :redirection_url, :sort_direction, :sort_column
9
+ :display_type, :action_type, :redirection_url, :sort_direction, :sort_column, :accessible_by
10
10
 
11
11
  VALID_SORT_DIRECTION = Set[:asc, :desc].freeze
12
12
 
@@ -34,6 +34,14 @@ module CmAdmin
34
34
  self.action_type = :default
35
35
  self.sort_column = :created_at
36
36
  self.sort_direction = :desc
37
+ self.accessible_by = CmAdmin.authorized_roles
38
+ end
39
+
40
+ def set_values(page_title, page_description, partial, accessible_by)
41
+ self.page_title = page_title
42
+ self.page_description = page_description
43
+ self.partial = partial
44
+ self.accessible_by = (CmAdmin.authorized_roles.dup << accessible_by).flatten.compact.uniq if accessible_by
37
45
  end
38
46
 
39
47
  class << self
@@ -5,7 +5,7 @@ module CmAdmin
5
5
 
6
6
  def show(params)
7
7
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
8
- @ar_object = @ar_model.find(params[:id])
8
+ @ar_object = @ar_model.name.classify.constantize.find(params[:id])
9
9
  end
10
10
 
11
11
  def index(params)
@@ -21,11 +21,11 @@ module CmAdmin
21
21
 
22
22
  def edit(params)
23
23
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'edit')
24
- @ar_object = @ar_model.find(params[:id])
24
+ @ar_object = @ar_model.name.classify.constantize.find(params[:id])
25
25
  end
26
26
 
27
27
  def update(params)
28
- @ar_object = @ar_model.find(params[:id])
28
+ @ar_object = @ar_model.name.classify.constantize.find(params[:id])
29
29
  @ar_object.assign_attributes(resource_params(params))
30
30
  @ar_object
31
31
  end
@@ -10,32 +10,28 @@ module CmAdmin
10
10
  # @current_action = CmAdmin::Models::CustomAction.find_by(self, name: name)
11
11
  end
12
12
 
13
- def cm_index(page_title: nil ,page_description: nil, &block)
13
+ def cm_index(page_title: nil, page_description: nil, partial: nil, accessible_by: nil, &block)
14
14
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'index')
15
- @current_action.page_title = page_title
16
- @current_action.page_description = page_description
15
+ @current_action.set_values(page_title, page_description, partial, accessible_by)
17
16
  yield
18
17
  # action.instance_eval(&block)
19
18
  end
20
19
 
21
- def cm_show(page_title: nil,page_description: nil,&block)
20
+ def cm_show(page_title: nil, page_description: nil, partial: nil, accessible_by: nil, &block)
22
21
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
23
- @current_action.page_title = page_title
24
- @current_action.page_description = page_description
22
+ @current_action.set_values(page_title, page_description, partial, accessible_by)
25
23
  yield
26
24
  end
27
25
 
28
- def cm_edit(page_title: nil,page_description: nil, &block)
26
+ def cm_edit(page_title: nil,page_description: nil, partial: nil, accessible_by: nil, &block)
29
27
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'edit')
30
- @current_action.page_title = page_title
31
- @current_action.page_description = page_description
28
+ @current_action.set_values(page_title, page_description, partial, accessible_by)
32
29
  yield
33
30
  end
34
31
 
35
- def cm_new(page_title: nil,page_description: nil,&block)
32
+ def cm_new(page_title: nil,page_description: nil, partial: nil, accessible_by: nil, &block)
36
33
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'new')
37
- @current_action.page_title = page_title
38
- @current_action.page_description = page_description
34
+ @current_action.set_values(page_title, page_description, partial, accessible_by)
39
35
  yield
40
36
  end
41
37
 
@@ -51,14 +47,16 @@ module CmAdmin
51
47
  end
52
48
  end
53
49
 
54
- def tab(tab_name, custom_action, associated_model: nil, layout_type: nil, layout: nil, partial: nil, &block)
50
+ def tab(tab_name, custom_action, associated_model: nil, layout_type: nil, layout: nil, partial: nil, accessible_by: nil, &block)
55
51
  if custom_action.to_s == ''
56
52
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
53
+ @current_action.accessible_by = (CmAdmin.authorized_roles.dup << accessible_by).flatten.compact.uniq if accessible_by
57
54
  @available_tabs << CmAdmin::Models::Tab.new(tab_name, '', &block)
58
55
  else
59
56
  action = CmAdmin::Models::Action.new(name: custom_action.to_s, verb: :get, path: ':id/'+custom_action,
60
57
  layout_type: layout_type, layout: layout, partial: partial, child_records: associated_model,
61
58
  action_type: :custom, display_type: :page)
59
+ action.accessible_by = (CmAdmin.authorized_roles.dup << accessible_by).flatten.compact.uniq if accessible_by
62
60
  @available_actions << action
63
61
  @current_action = action
64
62
  @available_tabs << CmAdmin::Models::Tab.new(tab_name, custom_action, &block)
@@ -119,11 +117,12 @@ module CmAdmin
119
117
  # end
120
118
  # end
121
119
  # end
122
- def custom_action(name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, display_if: lambda { |arg| return true }, route_type: nil, &block)
120
+ def custom_action(name: nil, verb: nil, layout: nil, layout_type: nil, partial: nil, path: nil, display_type: nil, display_if: lambda { |arg| return true }, route_type: nil, accessible_by: nil, &block)
123
121
  action = CmAdmin::Models::CustomAction.new(
124
122
  name: name, verb: verb, layout: layout, layout_type: layout_type, partial: partial, path: path,
125
123
  parent: self.current_action.name, display_type: display_type, display_if: display_if,
126
124
  action_type: :custom, route_type: route_type, &block)
125
+ action.accessible_by = (CmAdmin.authorized_roles.dup << accessible_by).flatten.compact.uniq if accessible_by
127
126
  @available_actions << action
128
127
  # self.class.class_eval(&block)
129
128
  end
@@ -2,7 +2,8 @@ module CmAdmin
2
2
  module Models
3
3
  class Field
4
4
 
5
- attr_accessor :field_name, :label, :header, :field_type, :format, :precision, :helper_method, :preview, :custom_link, :precision
5
+ attr_accessor :field_name, :label, :header, :field_type, :format, :precision,
6
+ :helper_method, :preview, :custom_link, :precision, :prefix, :suffix
6
7
 
7
8
  def initialize(field_name, attributes = {})
8
9
  @field_name = field_name
@@ -1,3 +1,3 @@
1
1
  module CmAdmin
2
- VERSION = "0.5.6"
2
+ VERSION = "0.5.9"
3
3
  end
@@ -5,7 +5,7 @@ module CmAdmin
5
5
  def show_field(ar_object, field)
6
6
  content_tag(:div, class: "info-split") do
7
7
  concat show_field_label(ar_object, field)
8
- concat show_field_value(ar_object, field)
8
+ concat value_with_prefix_and_suffix(ar_object, field)
9
9
  end
10
10
  end
11
11
 
@@ -14,9 +14,18 @@ module CmAdmin
14
14
  p = field.label.present? ? field.label.to_s : field.field_name.to_s.titleize
15
15
  end
16
16
  end
17
-
18
- def show_field_value(ar_object, field)
17
+
18
+ def value_with_prefix_and_suffix(ar_object, field)
19
+ value = show_field_value(ar_object, field)
19
20
  content_tag(:div, class: "info-split__rhs") do
21
+ concat field.prefix
22
+ concat value
23
+ concat field.suffix
24
+ end
25
+ end
26
+
27
+ def show_field_value(ar_object, field)
28
+ content_tag(:span) do
20
29
  case field.field_type || :string
21
30
  when :integer
22
31
  ar_object.send(field.field_name).to_s
@@ -43,14 +52,14 @@ module CmAdmin
43
52
  ar_object.send(field.field_name).to_s.titleize
44
53
  when :tag
45
54
  content_tag :span, class: "status-tag default-#{ar_object.send(field.field_name.to_s + '_before_type_cast')}" do
46
- ar_object.send(field.field_name).to_s.titleize
55
+ ar_object.send(field.field_name).to_s.upcase
47
56
  end
48
57
  when :attachment
49
58
  concat show_attachment_value(ar_object, field)
50
59
  when :drawer
51
60
  content_tag :span do
52
61
  concat content_tag(:span, truncate(ar_object.send(field.field_name).to_s, length: 25))
53
- concat content_tag(:a, " View", class: "drawer-btn")
62
+ concat content_tag(:span, 'View', class: 'drawer-btn')
54
63
  end
55
64
  end
56
65
  end
@@ -60,12 +69,12 @@ module CmAdmin
60
69
  if ar_object.send(field.field_name).attached?
61
70
  if ar_object.send(field.field_name).class.name.include?('One')
62
71
  content_tag :a, href: rails_blob_path(ar_object.send(field.field_name), disposition: "attachment") do
63
- ar_object.send(field.field_name).filename.to_s
72
+ ar_object.send(field.field_name).filename.to_s
64
73
  end
65
74
  elsif ar_object.send(field.field_name).class.name.include?('Many')
66
75
  ar_object.send(field.field_name).map do |asset|
67
76
  content_tag :a, href: rails_blob_path(asset, disposition: "attachment") do
68
- asset.filename.to_s
77
+ asset.filename.to_s
69
78
  end
70
79
  end.join("\n").html_safe
71
80
  end
@@ -44,12 +44,14 @@ module CmAdmin
44
44
  if field.input_type.eql?(:hidden)
45
45
  concat input_field_for_column(f, field)
46
46
  else
47
- concat f.label field.label, class: 'field-label'
48
- concat tag.br
49
- concat(content_tag(:div, class: "datetime-wrapper") do
50
- concat input_field_for_column(f, field)
47
+ concat(content_tag(:div, class: "input-wrapper #{field.disabled ? 'disabled' : ''}") do
48
+ concat f.label field.label, field.label, class: "field-label"
49
+ concat tag.br
50
+ concat(content_tag(:div, class: "datetime-wrapper") do
51
+ concat input_field_for_column(f, field)
52
+ end)
53
+ concat tag.p resource.errors[field.field_name].first if resource.errors[field.field_name].present?
51
54
  end)
52
- concat tag.p resource.errors[field.field_name].first if resource.errors[field.field_name].present?
53
55
  end
54
56
  end
55
57
  else
@@ -4,26 +4,28 @@ module CmAdmin
4
4
  module NavigationHelper
5
5
  include Pagy::Frontend
6
6
  def navigation_links(navigation_type)
7
- CmAdmin.cm_admin_models.map { |model|
7
+ CmAdmin.config.cm_admin_models.map { |model|
8
8
  if model.is_visible_on_sidebar
9
9
  path = CmAdmin::Engine.mount_path + '/' + model.name.underscore.pluralize
10
- if navigation_type == "sidebar"
11
- content_tag(:a, href: path) do
12
- content_tag(:div, class: 'menu-item') do
13
- content_tag(:span, class: 'menu-icon') do
14
- concat tag.i class: 'fa fa-th-large'
15
- end +
16
- model.name
10
+ if policy([:cm_admin, model.name.classify.constantize]).index?
11
+ if navigation_type == "sidebar"
12
+ content_tag(:a, href: path) do
13
+ content_tag(:div, class: 'menu-item') do
14
+ content_tag(:span, class: 'menu-icon') do
15
+ concat tag.i class: "#{model.icon_name}"
16
+ end +
17
+ model.name.pluralize
18
+ end
17
19
  end
18
- end
19
- elsif navigation_type == "quick_links"
20
- content_tag(:a, href: path, class: 'visible') do
21
- content_tag(:div, class: 'result-item') do
22
- content_tag(:span) do
23
- concat tag.i class: 'fa fa-th-large'
24
- end +
25
- content_tag(:span) do
26
- model.name
20
+ elsif navigation_type == "quick_links"
21
+ content_tag(:a, href: path, class: 'visible') do
22
+ content_tag(:div, class: 'result-item') do
23
+ content_tag(:span) do
24
+ concat tag.i class: "#{model.icon_name}"
25
+ end +
26
+ content_tag(:span) do
27
+ model.name
28
+ end
27
29
  end
28
30
  end
29
31
  end
@@ -15,8 +15,6 @@ module CmAdmin
15
15
  case action_name
16
16
  when 'index'
17
17
  title + " list record"
18
- when 'show'
19
- title + " detail"
20
18
  when 'new'
21
19
  title + " create record"
22
20
  when 'edit'
@@ -36,8 +34,6 @@ module CmAdmin
36
34
  case action_name
37
35
  when 'index'
38
36
  title + " list record"
39
- when 'show'
40
- title + " detail"
41
37
  when 'new'
42
38
  title + " new record"
43
39
  when 'edit'
data/lib/cm_admin.rb CHANGED
@@ -4,14 +4,17 @@ require 'cm_admin/engine'
4
4
  require 'cm_admin/model'
5
5
  require 'cm_admin/view_helpers'
6
6
  require 'cm_admin/utils'
7
+ require 'cm_admin/configuration'
7
8
 
8
9
  module CmAdmin
9
10
  class Error < StandardError; end
10
11
 
11
- mattr_accessor :layout
12
+ mattr_accessor :layout, :authorized_roles
12
13
  mattr_accessor :included_models, :cm_admin_models
14
+ @@authorized_roles ||= []
13
15
  @@included_models ||= []
14
16
  @@cm_admin_models ||= []
17
+
15
18
 
16
19
  class << self
17
20
  def webpacker
@@ -21,15 +24,18 @@ module CmAdmin
21
24
  )
22
25
  end
23
26
 
24
- def setup
25
- yield self
27
+ def configure(&block)
28
+ instance_eval(&block)
26
29
  end
27
30
 
28
- def config(entity, &block)
31
+ def config
32
+ @config ||= Configuration.new
33
+ end
34
+
35
+ def initialize_model(entity, &block)
29
36
  if entity.is_a?(Class)
30
- unless CmAdmin::Model.find_by({name: entity.name})
31
- @@cm_admin_models << CmAdmin::Model.new(entity, &block)
32
- end
37
+ return if CmAdmin::Model.find_by({name: entity.name})
38
+ config.cm_admin_models << CmAdmin::Model.new(entity, &block)
33
39
  end
34
40
  end
35
41
  end
@@ -1,26 +1,16 @@
1
1
  require 'rails/generators'
2
2
 
3
- def add_required_gems
4
- gem 'slim'
5
- gem 'simple_form'
6
- system("yarn add bootstrap")
7
- system("yarn add @fortawesome/fontawesome-free")
8
- system("yarn add select2")
9
- system("yarn add daterangepicker")
10
- system("yarn add jgrowl")
11
- end
12
-
13
- def copy_layout_file
14
- copy_file "layouts/_side_navbar.html.slim", "app/views/layouts/_side_navbar.html.slim"
15
- copy_file "layouts/_navbar.html.slim", "app/views/layouts/_navbar.html.slim"
16
- remove_file "app/views/layouts/application.html.erb"
17
- copy_file "layouts/application.html.slim", "app/views/layouts/application.html.slim"
18
- end
3
+ module CmAdmin
4
+ module Generators
5
+ class InstallGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('templates', __dir__)
19
7
 
20
- def copy_asset_file
21
- copy_file "assets/images/cm.png", "app/assets/images/cm.png"
22
- directory "assets/stylesheets/", "app/assets/stylesheets/"
23
- remove_file "app/assets/stylesheets/application.css"
8
+ def copy_initializer
9
+ copy_file 'cm_admin_initializer.rb', 'config/initializers/cm_admin.rb'
10
+ copy_file 'custom.js', 'app/assets/javascripts/custom.js'
11
+ copy_file 'custom.css', 'app/assets/stylesheets/custom.css'
12
+ route 'mount CmAdmin::Engine => "/admin"'
13
+ end
24
14
  end
25
15
  end
26
- end
16
+ end
@@ -0,0 +1,4 @@
1
+ CmAdmin.setup do |config|
2
+ # Sets the default layout to be used for admin
3
+ config.layout = 'admin'
4
+ end
File without changes
File without changes
metadata CHANGED
@@ -1,16 +1,16 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cm-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.6
4
+ version: 0.5.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - sajinmp
8
8
  - anbublacky
9
9
  - AdityaTiwari2102
10
- autorequire:
10
+ autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-03-02 00:00:00.000000000 Z
13
+ date: 2022-03-24 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: pagy
@@ -82,6 +82,20 @@ dependencies:
82
82
  - - "~>"
83
83
  - !ruby/object:Gem::Version
84
84
  version: 1.2.15
85
+ - !ruby/object:Gem::Dependency
86
+ name: pundit
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: 2.2.0
92
+ type: :runtime
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - "~>"
97
+ - !ruby/object:Gem::Version
98
+ version: 2.2.0
85
99
  description: This is an admin panel gem
86
100
  email:
87
101
  - sajinprasadkm@gmail.com
@@ -138,6 +152,7 @@ files:
138
152
  - app/javascript/packs/cm_admin/quick_search.js
139
153
  - app/javascript/packs/cm_admin/scaffolds.js
140
154
  - app/javascript/stylesheets/cm_admin/application.scss
155
+ - app/policies/application_policy.rb
141
156
  - app/views/cm_admin/main/_associated_table.html.slim
142
157
  - app/views/cm_admin/main/_cm_pagy_nav.html.slim
143
158
  - app/views/cm_admin/main/_drawer.html.slim
@@ -154,7 +169,9 @@ files:
154
169
  - app/views/cm_admin/main/index.html.slim
155
170
  - app/views/cm_admin/main/new.html.slim
156
171
  - app/views/cm_admin/main/show.html.slim
172
+ - app/views/cm_admin/static/dashboard.html.slim
157
173
  - app/views/cm_admin/static/error_401.html.slim
174
+ - app/views/cm_admin/static/error_403.html.slim
158
175
  - app/views/layouts/_custom_action_modals.html.slim
159
176
  - app/views/layouts/_flash_message.html.slim
160
177
  - app/views/layouts/_left_sidebar_nav.html.slim
@@ -176,6 +193,7 @@ files:
176
193
  - config/webpacker.yml
177
194
  - lib/.DS_Store
178
195
  - lib/cm_admin.rb
196
+ - lib/cm_admin/configuration.rb
179
197
  - lib/cm_admin/constants.rb
180
198
  - lib/cm_admin/engine.rb
181
199
  - lib/cm_admin/model.rb
@@ -204,6 +222,9 @@ files:
204
222
  - lib/cm_admin/view_helpers/navigation_helper.rb
205
223
  - lib/cm_admin/view_helpers/page_info_helper.rb
206
224
  - lib/generators/cm_admin/install_generator.rb
225
+ - lib/generators/cm_admin/templates/cm_admin_initializer.rb
226
+ - lib/generators/cm_admin/templates/custom.css
227
+ - lib/generators/cm_admin/templates/custom.js
207
228
  - lib/tasks/webpack_install.rake
208
229
  - package.json
209
230
  - postcss.config.js
@@ -215,7 +236,7 @@ licenses:
215
236
  metadata:
216
237
  homepage_uri: https://github.com/commutatus/cm-admin
217
238
  source_code_uri: https://github.com/commutatus/cm-admin
218
- post_install_message:
239
+ post_install_message:
219
240
  rdoc_options: []
220
241
  require_paths:
221
242
  - lib
@@ -230,8 +251,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
230
251
  - !ruby/object:Gem::Version
231
252
  version: '0'
232
253
  requirements: []
233
- rubygems_version: 3.0.3
234
- signing_key:
254
+ rubygems_version: 3.2.3
255
+ signing_key:
235
256
  specification_version: 4
236
257
  summary: This is an admin panel gem
237
258
  test_files: []