cm-admin 0.6.1 → 0.6.4

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 2e28d75f3c079c84bbf3e36a395b277390810ae103b87f2678b15c5c12210257
4
- data.tar.gz: f207f2665af3246e6f285c626dcfc23bd2f6160b893e665311e4e0babf42f919
3
+ metadata.gz: 42bd38332aef8d07ca35563f166f706ece3c2da88fa5e22278694da5377bb983
4
+ data.tar.gz: 292d897394afa6ee6be6a1a1a970e88e77b7d9762d6859c86bafc273de20f619
5
5
  SHA512:
6
- metadata.gz: 2c1834f17fa138e419d25cd20140ee6e9b78594a3ce8d37f1834eb113f9e88def0b9532b09e3d4c0f0c3e5d1334ddb88d298274b4e70e12779d9e349732d215e
7
- data.tar.gz: 0e2781411e73d8ba757462451992f65292a47bb9d9042546a0b70486e7d38e6a60209bf4130ca08d47dc6617ecec75558f15f586c21c90187d998ba9ec74f699
6
+ metadata.gz: 29548bef18b577c1507ce3404a8055c3083d196c4ecaf03e62e1ccd1a9b9fa46ed128c411f95c3446fa8b95a50c245ad04d94c4a131a8b46d95bc41252e3953f
7
+ data.tar.gz: 4df3cd6b9d6d3a006798a58a292dfac7f77deaff586e622499d2474525c8060e10e4746993b53ed6f9d70d3a635acfab056ffa6ed418d9e5f5f1e4f4152b7c62
data/Gemfile.lock CHANGED
@@ -54,7 +54,7 @@ GEM
54
54
  method_source (1.0.0)
55
55
  mini_portile2 (2.8.0)
56
56
  minitest (5.15.0)
57
- nokogiri (1.13.3)
57
+ nokogiri (1.13.4)
58
58
  mini_portile2 (~> 2.8.0)
59
59
  racc (~> 1.4)
60
60
  pagy (4.11.0)
@@ -18,7 +18,6 @@
18
18
 
19
19
  &__table-container {
20
20
  padding: 20px;
21
- height: 100%;
22
21
  }
23
22
 
24
23
  .admin-table {
@@ -77,13 +76,14 @@
77
76
  overflow: auto;
78
77
  margin-top: 40px;
79
78
  margin-bottom: 50px;
80
- height: 280px;
79
+ height: calc(100vh - 365px);
81
80
  .cm-table {
82
81
  table-layout: fixed;
83
82
  position: relative;
84
83
  min-width: fit-content;
85
84
  border-collapse: collapse;
86
85
  border: 1px solid $grey-lighter-clr;
86
+ border-top-width: 0;
87
87
  border-radius: $radius-8;
88
88
  &__header {
89
89
  .header-row {
@@ -91,6 +91,7 @@
91
91
  width: 100%;
92
92
  position: relative;
93
93
  box-shadow: inset 0px -1px 0px rgba(148, 151, 155, 0.15);
94
+ border-top: 1px solid $grey-lighter-clr;
94
95
  th {
95
96
  @include font($size: $t6-text, $color: $ink-lighter-clr, $weight: bold);
96
97
  text-transform: uppercase;
@@ -129,7 +130,7 @@
129
130
  // height: 335px;
130
131
  display: block;
131
132
  position: relative;
132
- width: 100%;
133
+ width: 100%;
133
134
  .body-row {
134
135
  border-bottom: 1.21px solid rgb(240, 239, 239);
135
136
  td:nth-child(2){
@@ -138,7 +139,7 @@
138
139
  z-index: 2;
139
140
  background-color: #fff;
140
141
  }
141
-
142
+
142
143
  &:nth-last-child(1) {
143
144
  box-shadow: none;
144
145
  }
@@ -190,7 +191,6 @@
190
191
  justify-content: center;
191
192
  height: 100%;
192
193
  .popup-card {
193
- width:fit-content;
194
194
  .popup-option {
195
195
  a {
196
196
  font-weight: 500;
@@ -210,8 +210,8 @@
210
210
  }
211
211
  }
212
212
  .cm-table > thead {
213
- position:sticky;
214
- top:0;
213
+ position: sticky;
214
+ top: 0;
215
215
  background-color: #fff;
216
216
  z-index: 3;
217
217
  }
@@ -4,26 +4,12 @@
4
4
  font-size: $t4-text;
5
5
  line-height: 22px;
6
6
  padding: 4px;
7
- &.default-0 {
8
- color: $primary-text-clr;
9
- background: $grey-lighter-clr;
10
- }
11
- &.default-1 {
7
+ color: $primary-text-clr;
8
+ background: $grey-lighter-clr;
9
+ &.success {
12
10
  color: $green-regular-clr;
13
11
  background: $green-lightest-clr;
14
12
  }
15
- &.default-2 {
16
- color: $yellow-regular-clr;
17
- background: $yellow-lightest-clr;
18
- }
19
- &.default-3 {
20
- color: $red-regular-clr;
21
- background: $red-lightest-clr;
22
- }
23
- &.default-4 {
24
- color: $blue-regular-clr;
25
- background: $blue-lightest-clr;
26
- }
27
13
  }
28
14
 
29
15
  .filter-chip {
@@ -7,5 +7,11 @@ module CmAdmin
7
7
  def current_webpacker_instance
8
8
  CmAdmin.webpacker
9
9
  end
10
+
11
+ # Allow if policy is not defined.
12
+ def has_valid_policy(model_name, action_name)
13
+ return true unless policy([:cm_admin, model_name.classify.constantize]).methods.include?(:"#{action_name}?")
14
+ policy([:cm_admin, model_name.classify.constantize]).send(:"#{action_name}?")
15
+ end
10
16
  end
11
17
  end
@@ -12,38 +12,43 @@
12
12
  table.cm-table
13
13
  thead.cm-table__header
14
14
  tr.header-row
15
- th.check-box-space
16
- span
17
- input.cm-checkbox type="checkbox"
15
+ // To be added once bulk-select is finalized
16
+ / th.check-box-space
17
+ / span
18
+ / input.cm-checkbox type="checkbox"
18
19
  - @model.available_fields[@action.name.to_sym].each do |column|
19
20
  th = column.header
20
21
  tbody.cm-table__body
21
22
  - @associated_ar_object.data.each do |ar_object|
22
23
  tr.body-row
23
- td.check-box-space
24
- span
25
- input.cm-checkbox type="checkbox"
24
+ // To be added once bulk-select is finalized
25
+ / td.check-box-space
26
+ / span
27
+ / input.cm-checkbox type="checkbox"
26
28
  - @model.available_fields[@action.name.to_sym].each do |column|
27
29
  td
28
30
  span class="#{column.cm_css_class} text-ellipsis" = show_field_value(ar_object, column)
29
- td.row-action-cell
30
- .row-action-tool
31
- button.secondary-btn.tool-btn type="button"
32
- span
33
- i.fa.fa-bars.bolder
34
- span
35
- i.fa.fa-angle-down
36
- .popup-card.table-export-popup.hidden
37
- .popup-option
38
- a href="#{page_url('edit', ar_object)}"
39
- | Edit
40
- - @associated_model && @associated_model.available_actions.select{|act| act if act.route_type == 'member'}.each do |custom_action|
41
- - if custom_action.display_if.call(ar_object)
42
- .popup-option
43
- - if custom_action.display_type == :button
44
- = link_to custom_action.name.titleize, custom_action.path.gsub(':id', ar_object.id.to_s), method: custom_action.verb
45
- - elsif custom_action.display_type == :modal
46
- = link_to custom_action.name.titleize, '', data: { bs_toggle: "modal", bs_target: "##{custom_action.name.classify}Modal-#{ar_object.id.to_s}" }
31
+ - associated_model_actions = @associated_model && @associated_model.available_actions.select{|act| act if act.route_type == 'member'}
32
+ - if associated_model_actions.present?
33
+ td.row-action-cell
34
+ .row-action-tool
35
+ button.secondary-btn.tool-btn type="button"
36
+ span
37
+ i.fa.fa-bars.bolder
38
+ span
39
+ i.fa.fa-angle-down
40
+ .popup-card.table-export-popup.hidden
41
+ // To be added once the associated model has edit actions
42
+ / .popup-option
43
+ / a href="#{page_url('edit', ar_object)}"
44
+ / | Edit
45
+ - associated_model_actions.each do |custom_action|
46
+ - if custom_action.display_if.call(ar_object)
47
+ .popup-option
48
+ - if custom_action.display_type == :button
49
+ = link_to custom_action.name.titleize, custom_action.path.gsub(':id', ar_object.id.to_s), method: custom_action.verb
50
+ - elsif custom_action.display_type == :modal
51
+ = link_to custom_action.name.titleize, '', data: { bs_toggle: "modal", bs_target: "##{custom_action.name.classify}Modal-#{ar_object.id.to_s}" }
47
52
 
48
53
  .cm-pagination
49
54
  .cm-pagination__lhs Showing #{@associated_ar_object.pagy.from} to #{@associated_ar_object.pagy.to} out of #{@associated_ar_object.pagy.count}
@@ -11,17 +11,18 @@
11
11
  table.cm-table
12
12
  thead.cm-table__header
13
13
  tr.header-row
14
- th.check-box-space
15
- span
16
- input.cm-checkbox type="checkbox"
14
+ // Select all checkbox feature to be added later
15
+ / th.check-box-space
16
+ / span
17
+ / input.cm-checkbox type="checkbox"
17
18
  - @model.available_fields[:index].each do |column|
18
19
  th = column.header
19
20
  tbody.cm-table__body
20
21
  - @ar_object.data.each do |ar_object|
21
22
  tr.body-row
22
- td.check-box-space
23
- span
24
- input.cm-checkbox type="checkbox"
23
+ / td.check-box-space
24
+ / span
25
+ / input.cm-checkbox type="checkbox"
25
26
  - @model.available_fields[:index].each_with_index do |column, index|
26
27
  td.text-ellipsis
27
28
  span class="#{column.field_type.to_s} #{column.cm_css_class} "
@@ -45,12 +46,18 @@
45
46
  .popup-card.table-export-popup.hidden
46
47
  - if edit_action.any? && policy([:cm_admin, @model.name.classify.constantize]).edit?
47
48
  = link_to "#{page_url('edit', ar_object)}" do
48
- .popup-option Edit
49
+ .popup-option
50
+ span
51
+ i.fa.fa-edit
52
+ | Edit
49
53
  - custom_actions.each do |custom_action|
50
- - if custom_action.name.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{custom_action.name}?")
54
+ - if custom_action.name.present? && has_valid_policy(@model.name, custom_action.name)
51
55
  - if custom_action.display_if.call(ar_object)
52
- = link_to custom_action.path.gsub(':id', ar_object.id.to_s), method: custom_action.verb do
53
- .popup-option = custom_action.name.titleize
56
+ = link_to cm_admin.send("#{@model.name.downcase}_index_path") + '/' + custom_action.path.gsub(':id', ar_object.id.to_s), method: custom_action.verb do
57
+ .popup-option
58
+ span
59
+ i class="#{custom_action.icon_name}"
60
+ = custom_action.name.titleize
54
61
 
55
62
  .cm-pagination
56
63
  .cm-pagination__lhs Showing #{@ar_object.pagy.from} to #{@ar_object.pagy.to} out of #{@ar_object.pagy.count}
@@ -1,6 +1,6 @@
1
1
  ul.nav.nav-pills
2
2
  - @model.available_tabs.each do |nav_item|
3
- - if nav_item.custom_action.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{nav_item.custom_action}?")
3
+ - if nav_item.custom_action.empty? || (nav_item.custom_action.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{nav_item.custom_action}?"))
4
4
  li.nav-item
5
5
  - nav_item_action_name = nav_item.custom_action.present? ? nav_item.custom_action : 'show'
6
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' : ''}"
@@ -1,7 +1,9 @@
1
1
  .cm-navbar
2
2
  .cm-navbar__lhs
3
- .bread-crumb-area
4
- = yield :bread_crumb
3
+ - if cm_admin.method_defined?(:"#{@model.name.downcase}_index_path") && (@model.current_action.name == 'show' || @model.current_action.layout_type.present?)
4
+ .bread-crumb-area
5
+ .breadcrumb-text
6
+ = link_to @model.name + ' /', cm_admin.send(:"#{@model.name.downcase}_index_path")
5
7
  .nav-title-area
6
8
  p.title-text = action_title
7
9
  p.title-sub-text = action_description
@@ -24,18 +26,10 @@
24
26
  - if new_action.any? && policy([:cm_admin, @model.name.classify.constantize]).new?
25
27
  = link_to 'Add', "#{page_url('new')}", class: 'primary-btn ml-2'
26
28
  - @model.available_actions.select{|act| act if act.route_type == 'collection'}.each do |custom_action|
27
- - if custom_action.name.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{custom_action.name}?")
28
- - if custom_action.display_type == :button
29
- = link_to custom_action.name.titleize, @model.ar_model.table_name + '/' + custom_action.path, class: 'primary-btn ml-2', method: custom_action.verb
30
- - elsif custom_action.display_type == :modal
31
- = link_to custom_action.name.titleize, '', class: 'primary-btn ml-2', data: { bs_toggle: "modal", bs_target: "##{custom_action.name.classify}Modal" }
29
+ = custom_action_items(custom_action, 'index')
32
30
  - elsif @model.current_action.name == 'show'
33
31
  - @model.available_actions.select{|act| act if act.route_type == 'member'}.each do |custom_action|
34
- - if custom_action.name.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{custom_action.name}?")
35
- - if custom_action.display_type == :button && custom_action.display_if.call(@ar_object)
36
- = link_to custom_action.name.titleize, custom_action.path.gsub(':id', params[:id]), class: 'primary-btn ml-2', method: custom_action.verb
37
- - elsif custom_action.display_type == :modal && custom_action.display_if.call(@ar_object)
38
- = link_to custom_action.name.titleize, '', class: 'primary-btn ml-2', data: { bs_toggle: "modal", bs_target: "##{custom_action.name.classify}Modal" }
32
+ = custom_action_items(custom_action, 'show')
39
33
 
40
34
  - edit_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('edit')}
41
35
  - if edit_action.any? && policy([:cm_admin, @model.name.classify.constantize]).edit?
@@ -6,4 +6,4 @@
6
6
  $.jGrowl("#{flash[:success]}", {theme: 'success'})
7
7
  - elsif flash[:alert].present?
8
8
  javascript:
9
- $.jGrowl("#{flash[:alert]}", {theme: 'error'})
9
+ $.jGrowl("#{flash[:alert].html_safe}", {theme: 'error'})
@@ -15,9 +15,6 @@ html
15
15
  script src="https://cdn.jsdelivr.net/npm/select2@4.1.0-rc.0/dist/js/select2.min.js"
16
16
  script src="https://raw.githack.com/SortableJS/Sortable/master/Sortable.js"
17
17
  body
18
- - flash.each do |type, msg|
19
- .alert class="alert-#{type}"
20
- = msg
21
18
  .cm-admin
22
19
  = render 'layouts/left_sidebar_nav'
23
20
  .panel-area
@@ -41,6 +38,6 @@ html
41
38
  = yield
42
39
  - else
43
40
  = yield
44
- = render 'layouts/flash_message'
41
+ = render 'layouts/cm_flash_message'
45
42
  = render 'layouts/custom_action_modals'
46
43
 
data/config/routes.rb CHANGED
@@ -10,7 +10,7 @@ CmAdmin::Engine.routes.draw do
10
10
 
11
11
  # Defining action routes for each model
12
12
  CmAdmin.config.cm_admin_models.each do |model|
13
- model.available_actions.sort_by {|act| act.class}.each do |act|
13
+ model.available_actions.sort_by {|act| act.name}.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}")
16
16
  end
@@ -45,7 +45,6 @@ module CmAdmin
45
45
  actions unless @actions_set
46
46
  $available_actions = @available_actions.dup
47
47
  self.class.all_actions.push(@available_actions)
48
- define_policy
49
48
  define_controller
50
49
  end
51
50
 
@@ -101,23 +100,6 @@ module CmAdmin
101
100
 
102
101
  private
103
102
 
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
-
121
103
  # Controller defined for each model
122
104
  # If model is User, controller will be UsersController
123
105
  def define_controller
@@ -135,7 +117,7 @@ module CmAdmin
135
117
  @model.current_action = @action
136
118
  @ar_object = @model.try(@action.parent || action_name, params)
137
119
  @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
120
+ authorize controller_name.classify.constantize, policy_class: "CmAdmin::#{controller_name.classify}Policy".constantize if defined? "CmAdmin::#{controller_name.classify}Policy".constantize
139
121
  aar_model = request.url.split('/')[-2].classify.constantize if params[:aar_id]
140
122
  @associated_ar_object = aar_model.find(params[:aar_id]) if params[:aar_id]
141
123
  nested_tables = @model.available_fields[:new].except(:fields).keys
@@ -157,10 +139,15 @@ module CmAdmin
157
139
  format.html { render '/cm_admin/main/'+action_name }
158
140
  end
159
141
  elsif %w(create update destroy).include?(action_name)
142
+ if %w(create update).include?(action_name)
143
+ redirect_url = CmAdmin::Engine.mount_path + "/#{@model.name.underscore.pluralize}/#{@ar_object.id}"
144
+ else
145
+ redirect_url = CmAdmin::Engine.mount_path + "/#{@model.name.underscore.pluralize}"
146
+ end
160
147
  if @ar_object.save
161
- format.html { redirect_to CmAdmin::Engine.mount_path + "/#{@model.name.underscore.pluralize}" }
148
+ format.html { redirect_to redirect_url, notice: "#{action_name.titleize} #{@ar_object.class.name.downcase} is successful" }
162
149
  else
163
- format.html { render '/cm_admin/main/new' }
150
+ format.html { render '/cm_admin/main/new', notice: "#{action_name.titleize} #{@ar_object.class.name.downcase} is unsuccessful" }
164
151
  end
165
152
  elsif action.action_type == :custom
166
153
  if action.child_records
@@ -169,11 +156,13 @@ module CmAdmin
169
156
  data = @action.parent == "index" ? @ar_object.data : @ar_object
170
157
  format.html { render action.partial }
171
158
  else
172
- if @action.code_block.call(@ar_object)
159
+ ar_object = @action.code_block.call(@ar_object)
160
+ if ar_object.errors.empty?
173
161
  redirect_url = @model.current_action.redirection_url || @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@ar_object.id}"
174
- format.html { redirect_to redirect_url }
162
+ format.html { redirect_to redirect_url, notice: "#{@action.name.titleize} is successful" }
175
163
  else
176
- format.html { redirect_to request.referrer }
164
+ error_messages = @ar_object.errors.full_messages.map{|error_message| "<li>#{error_message}</li>"}.join
165
+ format.html { redirect_to request.referrer, alert: "<b>#{@action.name.titleize} is unsuccessful</b><br /><ul>#{error_messages}</ul>" }
177
166
  end
178
167
  end
179
168
  elsif action.layout.present?
@@ -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, :accessible_by
9
+ :display_type, :action_type, :redirection_url, :sort_direction, :sort_column, :icon_name
10
10
 
11
11
  VALID_SORT_DIRECTION = Set[:asc, :desc].freeze
12
12
 
@@ -34,14 +34,13 @@ 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
37
+ self.icon_name = 'fa fa-th-large'
38
38
  end
39
39
 
40
- def set_values(page_title, page_description, partial, accessible_by)
40
+ def set_values(page_title, page_description, partial)
41
41
  self.page_title = page_title
42
42
  self.page_description = page_description
43
43
  self.partial = partial
44
- self.accessible_by = (CmAdmin.authorized_roles.dup << accessible_by).flatten.compact.uniq if accessible_by
45
44
  end
46
45
 
47
46
  class << self
@@ -2,7 +2,7 @@ module CmAdmin
2
2
  module Models
3
3
  class Column
4
4
  attr_accessor :field_name, :field_type, :header, :format, :prefix, :suffix, :exportable, :round,
5
- :cm_css_class, :link, :url, :custom_method, :helper_method, :managable, :lockable, :drawer_partial
5
+ :cm_css_class, :link, :url, :custom_method, :helper_method, :managable, :lockable, :drawer_partial, :tag_class
6
6
 
7
7
  def initialize(field_name, attributes = {})
8
8
  @field_name = field_name
@@ -24,6 +24,7 @@ module CmAdmin
24
24
  self.exportable = true
25
25
  self.managable = true
26
26
  self.lockable = false
27
+ self.tag_class = {}
27
28
  end
28
29
 
29
30
  #formatting value for different data types
@@ -5,7 +5,8 @@ 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.name.classify.constantize.find(params[:id])
8
+ scoped_model = "CmAdmin::#{self.name}Policy::Scope".constantize.new(Current.user, self.name.constantize).resolve
9
+ @ar_object = scoped_model.find(params[:id])
9
10
  end
10
11
 
11
12
  def index(params)
@@ -40,7 +41,8 @@ module CmAdmin
40
41
  sort_column = "created_at"
41
42
  sort_direction = %w[asc desc].include?(sort_params[:sort_direction]) ? sort_params[:sort_direction] : "asc"
42
43
  sort_params = {sort_column: sort_column, sort_direction: sort_direction}
43
- records = self.name.constantize.where(nil) if records.nil?
44
+
45
+ records = "CmAdmin::#{self.name}Policy::Scope".constantize.new(Current.user, self.name.constantize).resolve if records.nil?
44
46
  records = records.order("#{current_action.sort_column} #{current_action.sort_direction}")
45
47
 
46
48
  final_data = CmAdmin::Models::Filter.filtered_data(filter_params, records, @filters)
@@ -10,28 +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, partial: nil, accessible_by: nil, &block)
13
+ def cm_index(page_title: nil, page_description: nil, partial: nil, &block)
14
14
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'index')
15
- @current_action.set_values(page_title, page_description, partial, accessible_by)
15
+ @current_action.set_values(page_title, page_description, partial)
16
16
  yield
17
17
  # action.instance_eval(&block)
18
18
  end
19
19
 
20
- def cm_show(page_title: nil, page_description: nil, partial: nil, accessible_by: nil, &block)
20
+ def cm_show(page_title: nil, page_description: nil, partial: nil, &block)
21
21
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
22
- @current_action.set_values(page_title, page_description, partial, accessible_by)
22
+ @current_action.set_values(page_title, page_description, partial)
23
23
  yield
24
24
  end
25
25
 
26
- def cm_edit(page_title: nil,page_description: nil, partial: nil, accessible_by: nil, &block)
26
+ def cm_edit(page_title: nil,page_description: nil, partial: nil, &block)
27
27
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'edit')
28
- @current_action.set_values(page_title, page_description, partial, accessible_by)
28
+ @current_action.set_values(page_title, page_description, partial)
29
29
  yield
30
30
  end
31
31
 
32
- def cm_new(page_title: nil,page_description: nil, partial: nil, accessible_by: nil, &block)
32
+ def cm_new(page_title: nil,page_description: nil, partial: nil, &block)
33
33
  @current_action = CmAdmin::Models::Action.find_by(self, name: 'new')
34
- @current_action.set_values(page_title, page_description, partial, accessible_by)
34
+ @current_action.set_values(page_title, page_description, partial)
35
35
  yield
36
36
  end
37
37
 
@@ -47,16 +47,14 @@ module CmAdmin
47
47
  end
48
48
  end
49
49
 
50
- def tab(tab_name, custom_action, associated_model: nil, layout_type: nil, layout: nil, partial: nil, accessible_by: nil, &block)
50
+ def tab(tab_name, custom_action, associated_model: nil, layout_type: nil, layout: nil, partial: nil, &block)
51
51
  if custom_action.to_s == ''
52
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
54
53
  @available_tabs << CmAdmin::Models::Tab.new(tab_name, '', &block)
55
54
  else
56
55
  action = CmAdmin::Models::Action.new(name: custom_action.to_s, verb: :get, path: ':id/'+custom_action,
57
56
  layout_type: layout_type, layout: layout, partial: partial, child_records: associated_model,
58
57
  action_type: :custom, display_type: :page)
59
- action.accessible_by = (CmAdmin.authorized_roles.dup << accessible_by).flatten.compact.uniq if accessible_by
60
58
  @available_actions << action
61
59
  @current_action = action
62
60
  @available_tabs << CmAdmin::Models::Tab.new(tab_name, custom_action, &block)
@@ -117,12 +115,11 @@ module CmAdmin
117
115
  # end
118
116
  # end
119
117
  # end
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)
118
+ 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, icon_name: 'fa fa-th-large', &block)
121
119
  action = CmAdmin::Models::CustomAction.new(
122
120
  name: name, verb: verb, layout: layout, layout_type: layout_type, partial: partial, path: path,
123
121
  parent: self.current_action.name, display_type: display_type, display_if: display_if,
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
122
+ action_type: :custom, route_type: route_type, icon_name: icon_name, &block)
126
123
  @available_actions << action
127
124
  # self.class.class_eval(&block)
128
125
  end
@@ -1,3 +1,3 @@
1
1
  module CmAdmin
2
- VERSION = "0.6.1"
2
+ VERSION = "0.6.4"
3
3
  end
@@ -51,7 +51,8 @@ module CmAdmin
51
51
  when :enum
52
52
  ar_object.send(field.field_name).to_s.titleize
53
53
  when :tag
54
- content_tag :span, class: "status-tag default-#{ar_object.send(field.field_name.to_s + '_before_type_cast')}" do
54
+ tag_class = field.tag_class.dig("#{ar_object.send(field.field_name.to_s)}".to_sym).to_s
55
+ content_tag :span, class: "status-tag #{tag_class}" do
55
56
  ar_object.send(field.field_name).to_s.upcase
56
57
  end
57
58
  when :attachment
@@ -5,21 +5,21 @@ module CmAdmin
5
5
  value = field.custom_value || f.object.send(field.field_name)
6
6
  case field.input_type
7
7
  when :integer
8
- return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, data: {behaviour: 'integer-only'}
8
+ return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, placeholder: "Enter #{field.field_name.to_s.humanize.downcase}", data: { behaviour: 'integer-only' }
9
9
  when :decimal
10
- return f.number_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, data: {behaviour: 'decimal-only'}
10
+ return f.number_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, placeholder: "Enter #{field.field_name.to_s.downcase.gsub('_', ' ')}", data: { behaviour: 'decimal-only' }
11
11
  when :string
12
- return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value
12
+ return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, placeholder: "Enter #{field.field_name.to_s.downcase.gsub('_', ' ')}"
13
13
  when :single_select
14
- return f.select field.field_name, options_for_select(field.collection || []), {}, class: 'normal-input select-2', disabled: field.disabled
14
+ return f.select field.field_name, options_for_select((field.collection || []), value), {include_blank: "Select #{field.field_name.to_s.downcase.gsub('_', ' ')}"}, class: 'normal-input select-2', disabled: field.disabled
15
15
  when :multi_select
16
- return f.select field.field_name, options_for_select(field.collection || []), {}, class: 'normal-input select-2', disabled: field.disabled, multiple: true
16
+ return f.select field.field_name, options_for_select((field.collection || []), value), {include_blank: "Select #{field.field_name.to_s.downcase.gsub('_', ' ')}"}, class: 'normal-input select-2', disabled: field.disabled, multiple: true
17
17
  when :date
18
- return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, data: {behaviour: 'date-only'}
18
+ return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, placeholder: "Enter #{field.field_name.to_s.downcase.gsub('_', ' ')}", data: { behaviour: 'date-only' }
19
19
  when :date_time
20
- return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, data: {behaviour: 'date-time'}
20
+ return f.text_field field.field_name, class: 'normal-input', disabled: field.disabled, value: value, placeholder: "Enter #{field.field_name.to_s.downcase.gsub('_', ' ')}", data: { behaviour: 'date-time' }
21
21
  when :text
22
- return f.text_area field.field_name, class: 'normal-input'
22
+ return f.text_area field.field_name, class: 'normal-input', placeholder: "Enter #{field.field_name.to_s.downcase.gsub('_', ' ')}"
23
23
  when :single_file_upload
24
24
  return f.file_field field.field_name, class: 'normal-input'
25
25
  when :multi_file_upload
@@ -53,6 +53,31 @@ module CmAdmin
53
53
  base_path + "/#{ar_object.id}" + '/edit'
54
54
  end
55
55
  end
56
+
57
+ def custom_action_items(custom_action, current_action_name)
58
+ if custom_action.name.present? && policy([:cm_admin, @model.name.classify.constantize]).send(:"#{custom_action.name}?")
59
+ if custom_action.display_if.call(@ar_object)
60
+ case custom_action.display_type
61
+ when :button
62
+ custom_action_button(custom_action, current_action_name)
63
+ when :modal
64
+ custom_modal_button(custom_action)
65
+ end
66
+ end
67
+ end
68
+ end
69
+
70
+ def custom_action_button(custom_action, current_action_name)
71
+ if current_action_name == "index"
72
+ link_to custom_action.name.titleize, @model.ar_model.table_name + '/' + custom_action.path, class: 'secondary-btn ml-2', method: custom_action.verb
73
+ elsif current_action_name == "show"
74
+ link_to custom_action.name.titleize, custom_action.path.gsub(':id', params[:id]), class: 'secondary-btn ml-2', method: custom_action.verb
75
+ end
76
+ end
77
+
78
+ def custom_modal_button(custom_action)
79
+ link_to custom_action.name.titleize, '', class: 'secondary-btn ml-2', data: { bs_toggle: "modal", bs_target: "##{custom_action.name.classify}Modal" }
80
+ end
56
81
  end
57
82
  end
58
83
  end
@@ -7,8 +7,9 @@ module CmAdmin
7
7
 
8
8
  def copy_initializer
9
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'
10
+ copy_file 'custom.js', 'app/assets/javascripts/cm_admin/custom.js'
11
+ copy_file 'custom.css', 'app/assets/stylesheets/cm_admin/custom.css'
12
+ copy_file 'application_policy.rb', 'app/policies/application_policy.rb'
12
13
  route 'mount CmAdmin::Engine => "/admin"'
13
14
  end
14
15
  end
@@ -0,0 +1,13 @@
1
+ require 'rails/generators'
2
+
3
+ module CmAdmin
4
+ module Generators
5
+ class PolicyGenerator < Rails::Generators::NamedBase
6
+ source_root File.expand_path('templates', __dir__)
7
+
8
+ def copy_policy_files
9
+ template "policy.rb", "app/policies/cm_admin/#{file_name}_policy.rb"
10
+ end
11
+ end
12
+ end
13
+ end
@@ -17,7 +17,7 @@ class ApplicationPolicy
17
17
  end
18
18
 
19
19
  def create?
20
- false
20
+ true
21
21
  end
22
22
 
23
23
  def new?
@@ -43,7 +43,7 @@ class ApplicationPolicy
43
43
  end
44
44
 
45
45
  def resolve
46
- raise NotImplementedError, "You must define #resolve in #{self.class}"
46
+ scope.all
47
47
  end
48
48
 
49
49
  private
@@ -0,0 +1,8 @@
1
+ class CmAdmin::<%= class_name %>Policy < ApplicationPolicy
2
+ <%- available_action_names = (CmAdmin::Model.find_by({name: class_name}).available_actions.map{|action| action.name}.uniq - ['custom_action', 'new', 'edit']) %>
3
+ <%- available_action_names.each do |action_name| %>
4
+ def <%= action_name %>?
5
+ <%= CmAdmin.authorized_roles.map {|role| "@user.#{role}" }.join(' && ') %>
6
+ end
7
+ <% end %>
8
+ end
data/package.json CHANGED
@@ -13,7 +13,7 @@
13
13
  "flatpickr": "^4.6.9",
14
14
  "jgrowl": "^1.4.8",
15
15
  "jquery": "^3.6.0",
16
- "moment": "^2.29.1",
16
+ "moment": "^2.29.2",
17
17
  "popper.js": "^1.16.1",
18
18
  "turbolinks": "^5.2.0"
19
19
  },
data/yarn.lock CHANGED
@@ -4123,9 +4123,9 @@ minimatch@^3.0.4:
4123
4123
  brace-expansion "^1.1.7"
4124
4124
 
4125
4125
  minimist@^1.2.0, minimist@^1.2.5:
4126
- version "1.2.5"
4127
- resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.5.tgz#67d66014b66a6a8aaa0c083c5fd58df4e4e97602"
4128
- integrity sha512-FM9nNUYrRBAELZQT3xeZQ7fmMOBg6nWNmJKTcgsJeaLstP/UODVpGsr5OhXhhXg6f+qtJ8uiZ+PUxkDWcgIXLw==
4126
+ version "1.2.6"
4127
+ resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.6.tgz#8637a5b759ea0d6e98702cfb3a9283323c93af44"
4128
+ integrity sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==
4129
4129
 
4130
4130
  minipass-collect@^1.0.2:
4131
4131
  version "1.0.2"
@@ -4199,10 +4199,10 @@ mkdirp@^1.0.3, mkdirp@^1.0.4:
4199
4199
  resolved "https://registry.yarnpkg.com/mkdirp/-/mkdirp-1.0.4.tgz#3eb5ed62622756d79a5f0e2a221dfebad75c2f7e"
4200
4200
  integrity sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==
4201
4201
 
4202
- moment@^2.29.1, moment@^2.9.0:
4203
- version "2.29.1"
4204
- resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.1.tgz#b2be769fa31940be9eeea6469c075e35006fa3d3"
4205
- integrity sha512-kHmoybcPV8Sqy59DwNDY3Jefr64lK/by/da0ViFcuA4DH0vQg5Q6Ze5VimxkfQNSC+Mls/Kx53s7TjP1RhFEDQ==
4202
+ moment@^2.29.2, moment@^2.9.0:
4203
+ version "2.29.2"
4204
+ resolved "https://registry.yarnpkg.com/moment/-/moment-2.29.2.tgz#00910c60b20843bcba52d37d58c628b47b1f20e4"
4205
+ integrity sha512-UgzG4rvxYpN15jgCmVJwac49h9ly9NurikMWGPdVxm8GZD6XjkKPxDTjQQ43gtGgnV3X0cAyWDdP2Wexoquifg==
4206
4206
 
4207
4207
  move-concurrently@^1.0.1:
4208
4208
  version "1.0.1"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cm-admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.6.1
4
+ version: 0.6.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - sajinmp
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2022-03-25 00:00:00.000000000 Z
13
+ date: 2022-04-13 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: pagy
@@ -152,7 +152,6 @@ files:
152
152
  - app/javascript/packs/cm_admin/quick_search.js
153
153
  - app/javascript/packs/cm_admin/scaffolds.js
154
154
  - app/javascript/stylesheets/cm_admin/application.scss
155
- - app/policies/application_policy.rb
156
155
  - app/views/cm_admin/main/_associated_table.html.slim
157
156
  - app/views/cm_admin/main/_cm_pagy_nav.html.slim
158
157
  - app/views/cm_admin/main/_drawer.html.slim
@@ -172,8 +171,8 @@ files:
172
171
  - app/views/cm_admin/static/dashboard.html.slim
173
172
  - app/views/cm_admin/static/error_401.html.slim
174
173
  - app/views/cm_admin/static/error_403.html.slim
174
+ - app/views/layouts/_cm_flash_message.html.slim
175
175
  - app/views/layouts/_custom_action_modals.html.slim
176
- - app/views/layouts/_flash_message.html.slim
177
176
  - app/views/layouts/_left_sidebar_nav.html.slim
178
177
  - app/views/layouts/_quick_links.html.slim
179
178
  - app/views/layouts/cm_admin.html.slim
@@ -222,9 +221,12 @@ files:
222
221
  - lib/cm_admin/view_helpers/navigation_helper.rb
223
222
  - lib/cm_admin/view_helpers/page_info_helper.rb
224
223
  - lib/generators/cm_admin/install_generator.rb
224
+ - lib/generators/cm_admin/policy_generator.rb
225
+ - lib/generators/cm_admin/templates/application_policy.rb
225
226
  - lib/generators/cm_admin/templates/cm_admin_initializer.rb
226
227
  - lib/generators/cm_admin/templates/custom.css
227
228
  - lib/generators/cm_admin/templates/custom.js
229
+ - lib/generators/cm_admin/templates/policy.rb
228
230
  - lib/tasks/webpack_install.rake
229
231
  - package.json
230
232
  - postcss.config.js