cm-admin 0.7.2 → 0.7.5
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 +4 -4
- data/Gemfile.lock +8 -10
- data/README.md +1 -1
- data/app/controllers/cm_admin/application_controller.rb +1 -0
- data/app/controllers/cm_admin/resource_controller.rb +192 -0
- data/app/helpers/cm_admin/application_helper.rb +11 -0
- data/app/views/cm_admin/main/_associated_table.html.slim +11 -3
- data/app/views/cm_admin/main/_nested_fields.html.slim +1 -1
- data/app/views/cm_admin/main/_table.html.slim +8 -1
- data/app/views/cm_admin/main/_tabs.html.slim +5 -4
- data/lib/cm_admin/model.rb +12 -65
- data/lib/cm_admin/models/action.rb +10 -0
- data/lib/cm_admin/models/dsl_method.rb +3 -3
- data/lib/cm_admin/models/form_field.rb +1 -1
- data/lib/cm_admin/models/tab.rb +3 -2
- data/lib/cm_admin/version.rb +1 -1
- data/lib/cm_admin/view_helpers/form_field_helper.rb +12 -2
- data/lib/cm_admin/view_helpers/form_helper.rb +9 -0
- data/lib/cm_admin/view_helpers/page_info_helper.rb +2 -0
- data/lib/generators/cm_admin/add_authentication_generator.rb +31 -0
- data/lib/generators/cm_admin/templates/application_controller.rb +8 -0
- data/lib/generators/cm_admin/templates/authentication.rb +14 -0
- data/lib/generators/cm_admin/templates/cm_admin_initializer.rb +2 -0
- data/lib/generators/cm_admin/templates/current.rb +9 -0
- data/tmp/cache/webpacker/last-compilation-digest-development +1 -1
- metadata +7 -3
- data/lib/cm_admin/models/controller_method.rb +0 -86
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8603d897651307b80517b9918c60ab3d2d62abdc2931af5ea7d8def1453b4865
|
4
|
+
data.tar.gz: 0afafa900d9c51bee526e9781df8dd41baf1603cf768bb8db3e1d8353fc4adc0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '02398dcf148b0d90bd6de2dfd2fdeae4fd4d3353d75c33433a75518da87c6d6c739349279f9f6f3a4632256c37e463009838e9ec21821d224728730a8656b87b'
|
7
|
+
data.tar.gz: 2f390a32636c40fdeb3afc5128ad824135565450d0b833aafc9ac828d8d4178d5dda2316e01f654a45266514a4a31e0b22985c41d3e1b10cf049ee56b6cf663c
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
cm-admin (0.5
|
4
|
+
cm-admin (0.7.5)
|
5
5
|
axlsx_rails (~> 0.6.1)
|
6
6
|
cocoon (~> 1.2.15)
|
7
7
|
pagy (~> 4.11.0)
|
@@ -47,29 +47,27 @@ GEM
|
|
47
47
|
htmlentities (4.3.4)
|
48
48
|
i18n (1.10.0)
|
49
49
|
concurrent-ruby (~> 1.0)
|
50
|
-
loofah (2.
|
50
|
+
loofah (2.18.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
|
-
mini_portile2 (2.8.0)
|
56
55
|
minitest (5.15.0)
|
57
|
-
nokogiri (1.13.
|
58
|
-
mini_portile2 (~> 2.8.0)
|
56
|
+
nokogiri (1.13.6-arm64-darwin)
|
59
57
|
racc (~> 1.4)
|
60
58
|
pagy (4.11.0)
|
61
59
|
pundit (2.2.0)
|
62
60
|
activesupport (>= 3.0.0)
|
63
61
|
racc (1.6.0)
|
64
|
-
rack (2.2.
|
62
|
+
rack (2.2.4)
|
65
63
|
rack-proxy (0.7.2)
|
66
64
|
rack
|
67
|
-
rack-test (
|
68
|
-
rack (>= 1.
|
65
|
+
rack-test (2.0.2)
|
66
|
+
rack (>= 1.3)
|
69
67
|
rails-dom-testing (2.0.3)
|
70
68
|
activesupport (>= 4.2.0)
|
71
69
|
nokogiri (>= 1.6)
|
72
|
-
rails-html-sanitizer (1.4.
|
70
|
+
rails-html-sanitizer (1.4.3)
|
73
71
|
loofah (~> 2.3)
|
74
72
|
railties (7.0.2.3)
|
75
73
|
actionpack (= 7.0.2.3)
|
@@ -107,7 +105,7 @@ GEM
|
|
107
105
|
rack-proxy (>= 0.6.1)
|
108
106
|
railties (>= 5.2)
|
109
107
|
semantic_range (>= 2.3.0)
|
110
|
-
zeitwerk (2.
|
108
|
+
zeitwerk (2.6.0)
|
111
109
|
|
112
110
|
PLATFORMS
|
113
111
|
ruby
|
data/README.md
CHANGED
@@ -30,7 +30,7 @@ You can find more detailed documentation [here](https://github.com/commutatus/cm
|
|
30
30
|
|
31
31
|
## Demo
|
32
32
|
|
33
|
-
For demo check [here](http://cm-admin.labs.commutatus.com
|
33
|
+
For demo check [here](http://cm-admin.labs.commutatus.com)
|
34
34
|
For demo repo check [here](https://github.com/commutatus/cm-admin-panel-demo)
|
35
35
|
|
36
36
|
## Development
|
@@ -0,0 +1,192 @@
|
|
1
|
+
module CmAdmin
|
2
|
+
class ResourceController < ApplicationController
|
3
|
+
include Pundit::Authorization
|
4
|
+
include Pagy::Backend
|
5
|
+
|
6
|
+
def cm_index(params)
|
7
|
+
@current_action = CmAdmin::Models::Action.find_by(@model, name: 'index')
|
8
|
+
# Based on the params the filter and pagination object to be set
|
9
|
+
@ar_object = filter_by(params, nil, @model.filter_params(params))
|
10
|
+
# resource_identifier
|
11
|
+
respond_to do |format|
|
12
|
+
if request.xhr?
|
13
|
+
format.html { render partial: '/cm_admin/main/table' }
|
14
|
+
else
|
15
|
+
format.html { render '/cm_admin/main/' + action_name }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def cm_show(params)
|
21
|
+
@current_action = CmAdmin::Models::Action.find_by(@model, name: 'show')
|
22
|
+
scoped_model = "CmAdmin::#{@model.name}Policy::Scope".constantize.new(Current.user, @model.name.constantize).resolve
|
23
|
+
@ar_object = scoped_model.find(params[:id])
|
24
|
+
resource_identifier
|
25
|
+
respond_to do |format|
|
26
|
+
format.html { render '/cm_admin/main/' + action_name }
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def cm_new(params)
|
31
|
+
@current_action = CmAdmin::Models::Action.find_by(@model, name: 'new')
|
32
|
+
@ar_object = @model.ar_model.new
|
33
|
+
resource_identifier
|
34
|
+
respond_to do |format|
|
35
|
+
format.html { render '/cm_admin/main/' + action_name }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def cm_edit(params)
|
40
|
+
@current_action = CmAdmin::Models::Action.find_by(@model, name: 'edit')
|
41
|
+
@ar_object = @model.ar_model.name.classify.constantize.find(params[:id])
|
42
|
+
resource_identifier
|
43
|
+
respond_to do |format|
|
44
|
+
format.html { render '/cm_admin/main/' + action_name }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def cm_update(params)
|
49
|
+
@ar_object = @model.ar_model.name.classify.constantize.find(params[:id])
|
50
|
+
@ar_object.assign_attributes(resource_params(params))
|
51
|
+
resource_identifier
|
52
|
+
resource_responder
|
53
|
+
end
|
54
|
+
|
55
|
+
def cm_create(params)
|
56
|
+
@ar_object = @model.ar_model.name.classify.constantize.new(resource_params(params))
|
57
|
+
resource_identifier
|
58
|
+
resource_responder
|
59
|
+
end
|
60
|
+
|
61
|
+
def cm_destroy(params)
|
62
|
+
@ar_object = @model.ar_model.name.classify.constantize.find(params[:id])
|
63
|
+
respond_to do |format|
|
64
|
+
if @ar_object.destroy
|
65
|
+
format.html { redirect_back fallback_location: cm_admin.send("#{@model.name.underscore}_index_path"), notice: "#{action_name.titleize} #{@ar_object.class.name.downcase} is successful" }
|
66
|
+
else
|
67
|
+
format.html { redirect_back fallback_location: cm_admin.send("#{@model.name.underscore}_index_path"), notice: "#{action_name.titleize} #{@ar_object.class.name.downcase} is unsuccessful" }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def cm_custom_method(params)
|
73
|
+
scoped_model = "CmAdmin::#{@model.name}Policy::Scope".constantize.new(Current.user, @model.name.constantize).resolve
|
74
|
+
resource_identifier
|
75
|
+
respond_to do |format|
|
76
|
+
if @action.action_type == :custom
|
77
|
+
if @action.child_records
|
78
|
+
format.html { render @action.layout }
|
79
|
+
elsif @action.display_type == :page
|
80
|
+
data = @action.parent == "index" ? @ar_object.data : @ar_object
|
81
|
+
format.html { render @action.partial }
|
82
|
+
else
|
83
|
+
ar_object = @action.code_block.call(@ar_object)
|
84
|
+
if ar_object.errors.empty?
|
85
|
+
redirect_url = @model.current_action.redirection_url || @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@ar_object.id}"
|
86
|
+
format.html { redirect_to redirect_url, notice: "#{@action.name.titleize} is successful" }
|
87
|
+
else
|
88
|
+
error_messages = ar_object.errors.full_messages.map{|error_message| "<li>#{error_message}</li>"}.join
|
89
|
+
format.html { redirect_to request.referrer, alert: "<b>#{@action.name.titleize} is unsuccessful</b><br /><ul>#{error_messages}</ul>" }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
def resource_identifier
|
97
|
+
@ar_object, @associated_model, @associated_ar_object = custom_controller_action(action_name, params.permit!) if !@ar_object.present? && params[:id].present?
|
98
|
+
authorize controller_name.classify.constantize, policy_class: "CmAdmin::#{controller_name.classify}Policy".constantize if defined? "CmAdmin::#{controller_name.classify}Policy".constantize
|
99
|
+
aar_model = request.url.split('/')[-2].classify.constantize if params[:aar_id]
|
100
|
+
@associated_ar_object = aar_model.find(params[:aar_id]) if params[:aar_id]
|
101
|
+
nested_tables = @model.available_fields[:new].except(:fields).keys
|
102
|
+
nested_tables += @model.available_fields[:edit].except(:fields).keys
|
103
|
+
@reflections = @model.ar_model.reflect_on_all_associations
|
104
|
+
nested_tables.each do |table_name|
|
105
|
+
reflection = @reflections.select {|x| x if x.name == table_name}.first
|
106
|
+
if reflection.macro == :has_many
|
107
|
+
@ar_object.send(table_name).build if action_name == "new" || action_name == "edit"
|
108
|
+
elsif action_name == "new"
|
109
|
+
@ar_object.send(('build_' + table_name.to_s).to_sym)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def resource_responder
|
115
|
+
respond_to do |format|
|
116
|
+
if params["referrer"]
|
117
|
+
redirect_url = params["referrer"]
|
118
|
+
else
|
119
|
+
redirect_url = CmAdmin::Engine.mount_path + "/#{@model.name.underscore.pluralize}/#{@ar_object.id}"
|
120
|
+
end
|
121
|
+
if @ar_object.save
|
122
|
+
format.html { redirect_to redirect_url, notice: "#{action_name.titleize} #{@ar_object.class.name.downcase} is successful" }
|
123
|
+
else
|
124
|
+
format.html { render '/cm_admin/main/new', notice: "#{action_name.titleize} #{@ar_object.class.name.downcase} is unsuccessful" }
|
125
|
+
end
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
def custom_controller_action(action_name, params)
|
130
|
+
current_action = CmAdmin::Models::Action.find_by(@model, name: action_name.to_s)
|
131
|
+
if current_action
|
132
|
+
@current_action = current_action
|
133
|
+
@ar_object = @model.ar_model.name.classify.constantize.find(params[:id])
|
134
|
+
if @current_action.child_records
|
135
|
+
child_records = @ar_object.send(@current_action.child_records)
|
136
|
+
@associated_model = CmAdmin::Model.find_by(name: @model.ar_model.reflect_on_association(@current_action.child_records).klass.name)
|
137
|
+
if child_records.is_a? ActiveRecord::Relation
|
138
|
+
@associated_ar_object = filter_by(params, child_records)
|
139
|
+
else
|
140
|
+
@associated_ar_object = child_records
|
141
|
+
end
|
142
|
+
return @ar_object, @associated_model, @associated_ar_object
|
143
|
+
end
|
144
|
+
return @ar_object
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
def filter_by(params, records, filter_params={}, sort_params={})
|
149
|
+
filtered_result = OpenStruct.new
|
150
|
+
sort_column = "created_at"
|
151
|
+
sort_direction = %w[asc desc].include?(sort_params[:sort_direction]) ? sort_params[:sort_direction] : "asc"
|
152
|
+
sort_params = {sort_column: sort_column, sort_direction: sort_direction}
|
153
|
+
|
154
|
+
records = "CmAdmin::#{@model.name}Policy::Scope".constantize.new(Current.user, @model.name.constantize).resolve if records.nil?
|
155
|
+
records = records.order("#{@current_action.sort_column} #{@current_action.sort_direction}")
|
156
|
+
|
157
|
+
final_data = CmAdmin::Models::Filter.filtered_data(filter_params, records, @model.filters)
|
158
|
+
pagy, records = pagy(final_data)
|
159
|
+
filtered_result.data = records
|
160
|
+
filtered_result.pagy = pagy
|
161
|
+
# filtered_result.facets = paginate(page, raw_data.size)
|
162
|
+
# filtered_result.sort = sort_params
|
163
|
+
# filtered_result.facets.sort = sort_params
|
164
|
+
return filtered_result
|
165
|
+
end
|
166
|
+
|
167
|
+
def resource_params(params)
|
168
|
+
permittable_fields = @permitted_fields || @model.ar_model.columns.map(&:name).reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym)
|
169
|
+
permittable_fields += @model.ar_model.name.constantize.reflect_on_all_associations.map {|x|
|
170
|
+
next if x.options[:polymorphic]
|
171
|
+
if x.class.name.include?('HasOne')
|
172
|
+
x.name.to_s.gsub('_attachment', '').gsub('rich_text_', '').to_sym
|
173
|
+
elsif x.class.name.include?('HasMany')
|
174
|
+
Hash[x.name.to_s.gsub('_attachment', ''), []]
|
175
|
+
end
|
176
|
+
}.compact
|
177
|
+
nested_tables = @model.available_fields[:new].except(:fields).keys
|
178
|
+
nested_tables += @model.available_fields[:edit].except(:fields).keys
|
179
|
+
nested_fields = nested_tables.uniq.map {|table|
|
180
|
+
Hash[
|
181
|
+
table.to_s + '_attributes',
|
182
|
+
table.to_s.classify.constantize.columns.map(&:name).reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym) + [:id, :_destroy]
|
183
|
+
]
|
184
|
+
}
|
185
|
+
permittable_fields += nested_fields
|
186
|
+
@model.ar_model.columns.map { |col| permittable_fields << col.name.split('_cents') if col.name.include?('_cents') }
|
187
|
+
|
188
|
+
params.require(@model.name.underscore.to_sym).permit(*permittable_fields)
|
189
|
+
end
|
190
|
+
|
191
|
+
end
|
192
|
+
end
|
@@ -13,5 +13,16 @@ module CmAdmin
|
|
13
13
|
return true unless policy([:cm_admin, model_name.classify.constantize]).methods.include?(:"#{action_name}?")
|
14
14
|
policy([:cm_admin, model_name.classify.constantize]).send(:"#{action_name}?")
|
15
15
|
end
|
16
|
+
|
17
|
+
def action(action_name)
|
18
|
+
case action_name.to_sym
|
19
|
+
when :update
|
20
|
+
return :edit
|
21
|
+
when :create
|
22
|
+
return :new
|
23
|
+
else
|
24
|
+
return action_name.to_sym
|
25
|
+
end
|
26
|
+
end
|
16
27
|
end
|
17
28
|
end
|
@@ -2,6 +2,11 @@
|
|
2
2
|
.table-top
|
3
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
|
+
- if @associated_model && @associated_model.available_actions.map(&:name).include?('new')
|
6
|
+
- association = @ar_object.class.reflect_on_all_associations.select{|x| x.name == @associated_model.name.tableize.to_sym }.first
|
7
|
+
- polymorphic_name = (association && association.inverse_of && association.inverse_of.options[:polymorphic]) ? association.inverse_of.name : ''
|
8
|
+
a href="#{CmAdmin::Engine.mount_path}/#{@associated_model.name.tableize}/new?associated_id=#{@ar_object.id}&associated_class=#{@ar_object.class.name.underscore}&polymorphic_name=#{polymorphic_name}&referrer=#{request.path}"
|
9
|
+
button.secondary-btn.column-btn Add
|
5
10
|
/ button.secondary-btn.column-btn data-target="#columnActionModal" data-toggle="modal" type="button"
|
6
11
|
/ span
|
7
12
|
/ i.fa.fa-columns.bolder
|
@@ -17,7 +22,7 @@
|
|
17
22
|
/ span
|
18
23
|
/ input.cm-checkbox type="checkbox"
|
19
24
|
- @model.available_fields[@action.name.to_sym].each do |column|
|
20
|
-
|
25
|
+
th = column.header
|
21
26
|
tbody.cm-table__body
|
22
27
|
- @associated_ar_object.data.each do |ar_object|
|
23
28
|
tr.body-row
|
@@ -25,9 +30,12 @@
|
|
25
30
|
/ td.check-box-space
|
26
31
|
/ span
|
27
32
|
/ input.cm-checkbox type="checkbox"
|
28
|
-
- @model.available_fields[@action.name.to_sym].
|
33
|
+
- @model.available_fields[@action.name.to_sym].each_with_index do |column, index|
|
29
34
|
td class="text-ellipsis"
|
30
|
-
|
35
|
+
- if index == 0 && @associated_model && @associated_model.available_actions.map(&:name).include?('show')
|
36
|
+
a href="#{CmAdmin::Engine.mount_path}/#{@associated_model.name.tableize}/#{ar_object.id}" = show_field_value(ar_object, column)
|
37
|
+
- else
|
38
|
+
span class="#{column.cm_css_class}" = show_field_value(ar_object, column)
|
31
39
|
- associated_model_actions = @associated_model && @associated_model.available_actions.select{|act| act if act.route_type == 'member'}
|
32
40
|
- if associated_model_actions.present?
|
33
41
|
td.row-action-cell
|
@@ -34,8 +34,9 @@
|
|
34
34
|
= render partial: column.drawer_partial, locals: { ar_object: ar_object}
|
35
35
|
|
36
36
|
- edit_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('edit')}
|
37
|
+
- destroy_action = @model.available_actions.select{|act| act if act.action_type.eql?(:default) && act.name.eql?('destroy')}
|
37
38
|
- custom_actions = @model.available_actions.select{|act| act if act.route_type == 'member' && [:button, :modal].include?(act.display_type)}
|
38
|
-
- if custom_actions.any? || edit_action.any?
|
39
|
+
- if custom_actions.any? || edit_action.any? || destroy_action.any?
|
39
40
|
td.row-action-cell
|
40
41
|
.row-action-tool
|
41
42
|
button.secondary-btn.tool-btn type="button"
|
@@ -50,6 +51,12 @@
|
|
50
51
|
span
|
51
52
|
i.fa.fa-edit
|
52
53
|
| Edit
|
54
|
+
- if destroy_action.any? && policy([:cm_admin, @model.name.classify.constantize]).destroy?
|
55
|
+
= link_to "#{page_url('destroy', ar_object)}", method: :delete do
|
56
|
+
.popup-option
|
57
|
+
span
|
58
|
+
i.fa.fa-trash
|
59
|
+
| Destroy
|
53
60
|
- custom_actions.each do |custom_action|
|
54
61
|
- if custom_action.name.present? && has_valid_policy(@model.name, custom_action.name)
|
55
62
|
- if custom_action.display_if.call(ar_object)
|
@@ -1,6 +1,7 @@
|
|
1
1
|
ul.nav.nav-pills
|
2
2
|
- @model.available_tabs.each do |nav_item|
|
3
|
-
- if nav_item.
|
4
|
-
|
5
|
-
-
|
6
|
-
|
3
|
+
- if nav_item.display_if.call(@ar_object)
|
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
|
+
li.nav-item
|
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/#{@model.name.underscore.pluralize}/#{@ar_object.id}/#{nav_item.custom_action}", class: "nav-link #{ nav_item_action_name == action_name ? 'active' : ''}"
|
data/lib/cm_admin/model.rb
CHANGED
@@ -10,7 +10,6 @@ require_relative 'models/export'
|
|
10
10
|
require_relative 'models/cm_show_section'
|
11
11
|
require_relative 'models/tab'
|
12
12
|
require_relative 'models/dsl_method'
|
13
|
-
require_relative 'models/controller_method'
|
14
13
|
require 'pagy'
|
15
14
|
require 'axlsx'
|
16
15
|
require 'cocoon'
|
@@ -21,7 +20,6 @@ module CmAdmin
|
|
21
20
|
include Pagy::Backend
|
22
21
|
include Models::Blocks
|
23
22
|
include Models::DslMethod
|
24
|
-
include Models::ControllerMethod
|
25
23
|
attr_accessor :available_actions, :actions_set, :available_fields, :permitted_fields,
|
26
24
|
:current_action, :params, :filters, :available_tabs, :icon_name
|
27
25
|
attr_reader :name, :ar_model, :is_visible_on_sidebar
|
@@ -89,12 +87,13 @@ module CmAdmin
|
|
89
87
|
@icon_name = name
|
90
88
|
end
|
91
89
|
|
90
|
+
# Shared between export controller and resource controller
|
92
91
|
def filter_params(params)
|
93
92
|
# OPTIMIZE: Need to check if we can permit the filter_params in a better way
|
94
|
-
date_columns =
|
95
|
-
range_columns =
|
96
|
-
single_select_columns =
|
97
|
-
multi_select_columns =
|
93
|
+
date_columns = self.filters.select{|x| x.filter_type.eql?(:date)}.map(&:db_column_name)
|
94
|
+
range_columns = self.filters.select{|x| x.filter_type.eql?(:range)}.map(&:db_column_name)
|
95
|
+
single_select_columns = self.filters.select{|x| x.filter_type.eql?(:single_select)}.map(&:db_column_name)
|
96
|
+
multi_select_columns = self.filters.select{|x| x.filter_type.eql?(:multi_select)}.map{|x| Hash["#{x.db_column_name}", []]}
|
98
97
|
|
99
98
|
params.require(:filters).permit(:search, date: date_columns, range: range_columns, single_select: single_select_columns, multi_select: multi_select_columns) if params[:filters]
|
100
99
|
end
|
@@ -104,7 +103,7 @@ module CmAdmin
|
|
104
103
|
# Controller defined for each model
|
105
104
|
# If model is User, controller will be UsersController
|
106
105
|
def define_controller
|
107
|
-
klass = Class.new(CmAdmin::
|
106
|
+
klass = Class.new(CmAdmin::ResourceController) do
|
108
107
|
include Pundit::Authorization
|
109
108
|
rescue_from Pundit::NotAuthorizedError, with: :user_not_authorized
|
110
109
|
|
@@ -116,66 +115,14 @@ module CmAdmin
|
|
116
115
|
@model.params = params
|
117
116
|
@action = CmAdmin::Models::Action.find_by(@model, name: action_name)
|
118
117
|
@model.current_action = @action
|
119
|
-
|
120
|
-
@ar_object
|
121
|
-
authorize controller_name.classify.constantize, policy_class: "CmAdmin::#{controller_name.classify}Policy".constantize if defined? "CmAdmin::#{controller_name.classify}Policy".constantize
|
122
|
-
aar_model = request.url.split('/')[-2].classify.constantize if params[:aar_id]
|
123
|
-
@associated_ar_object = aar_model.find(params[:aar_id]) if params[:aar_id]
|
124
|
-
nested_tables = @model.available_fields[:new].except(:fields).keys
|
125
|
-
nested_tables += @model.available_fields[:edit].except(:fields).keys
|
126
|
-
@reflections = @model.ar_model.reflect_on_all_associations
|
127
|
-
nested_tables.each do |table_name|
|
128
|
-
reflection = @reflections.select {|x| x if x.name == table_name}.first
|
129
|
-
if reflection.macro == :has_many
|
130
|
-
@ar_object.send(table_name).build if action_name == "new" || action_name == "edit"
|
131
|
-
else
|
132
|
-
@ar_object.send(('build_' + table_name.to_s).to_sym) if action_name == "new"
|
133
|
-
end
|
134
|
-
end
|
135
|
-
respond_to do |format|
|
136
|
-
if %w(show index new edit).include?(action_name)
|
137
|
-
if request.xhr? && action_name.eql?('index')
|
138
|
-
format.html { render partial: '/cm_admin/main/table' }
|
139
|
-
else
|
140
|
-
format.html { render '/cm_admin/main/'+action_name }
|
141
|
-
end
|
142
|
-
elsif %w(create update destroy).include?(action_name)
|
143
|
-
if %w(create update).include?(action_name)
|
144
|
-
redirect_url = CmAdmin::Engine.mount_path + "/#{@model.name.underscore.pluralize}/#{@ar_object.id}"
|
145
|
-
else
|
146
|
-
redirect_url = CmAdmin::Engine.mount_path + "/#{@model.name.underscore.pluralize}"
|
147
|
-
end
|
148
|
-
if @ar_object.save
|
149
|
-
format.html { redirect_to redirect_url, notice: "#{action_name.titleize} #{@ar_object.class.name.downcase} is successful" }
|
150
|
-
else
|
151
|
-
format.html { render '/cm_admin/main/new', notice: "#{action_name.titleize} #{@ar_object.class.name.downcase} is unsuccessful" }
|
152
|
-
end
|
153
|
-
elsif action.action_type == :custom
|
154
|
-
if action.child_records
|
155
|
-
format.html { render action.layout }
|
156
|
-
elsif action.display_type == :page
|
157
|
-
data = @action.parent == "index" ? @ar_object.data : @ar_object
|
158
|
-
format.html { render action.partial }
|
159
|
-
else
|
160
|
-
ar_object = @action.code_block.call(@ar_object)
|
161
|
-
if ar_object.errors.empty?
|
162
|
-
redirect_url = @model.current_action.redirection_url || @action.redirection_url || request.referrer || "/cm_admin/#{@model.ar_model.table_name}/#{@ar_object.id}"
|
163
|
-
format.html { redirect_to redirect_url, notice: "#{@action.name.titleize} is successful" }
|
164
|
-
else
|
165
|
-
error_messages = ar_object.errors.full_messages.map{|error_message| "<li>#{error_message}</li>"}.join
|
166
|
-
format.html { redirect_to request.referrer, alert: "<b>#{@action.name.titleize} is unsuccessful</b><br /><ul>#{error_messages}</ul>" }
|
167
|
-
end
|
168
|
-
end
|
169
|
-
elsif action.layout.present?
|
170
|
-
if request.xhr? && action.partial.present?
|
171
|
-
format.html { render partial: action.partial }
|
172
|
-
else
|
173
|
-
format.html { render action.layout }
|
174
|
-
end
|
175
|
-
end
|
176
|
-
end
|
118
|
+
send(@action.controller_action_name, params)
|
119
|
+
# @ar_object = @model.try(@action.parent || action_name, params)
|
177
120
|
end
|
178
121
|
end
|
122
|
+
|
123
|
+
def pundit_user
|
124
|
+
Current.user
|
125
|
+
end
|
179
126
|
private
|
180
127
|
|
181
128
|
def user_not_authorized
|
@@ -43,6 +43,16 @@ module CmAdmin
|
|
43
43
|
self.partial = partial
|
44
44
|
end
|
45
45
|
|
46
|
+
def controller_action_name
|
47
|
+
if self.action_type == :custom
|
48
|
+
'cm_custom_method'
|
49
|
+
elsif self.parent
|
50
|
+
'cm_' + self.parent
|
51
|
+
else
|
52
|
+
'cm_' + name
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
46
56
|
class << self
|
47
57
|
def find_by(model, search_hash)
|
48
58
|
model.available_actions.find { |i| i.name == search_hash[:name] }
|
@@ -39,17 +39,17 @@ module CmAdmin
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
-
def tab(tab_name, custom_action, associated_model: nil, layout_type: nil, layout: nil, partial: nil, &block)
|
42
|
+
def tab(tab_name, custom_action, associated_model: nil, layout_type: nil, layout: nil, partial: nil, display_if: nil, &block)
|
43
43
|
if custom_action.to_s == ''
|
44
44
|
@current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
|
45
|
-
@available_tabs << CmAdmin::Models::Tab.new(tab_name, '', &block)
|
45
|
+
@available_tabs << CmAdmin::Models::Tab.new(tab_name, '', display_if, &block)
|
46
46
|
else
|
47
47
|
action = CmAdmin::Models::Action.new(name: custom_action.to_s, verb: :get, path: ':id/'+custom_action,
|
48
48
|
layout_type: layout_type, layout: layout, partial: partial, child_records: associated_model,
|
49
49
|
action_type: :custom, display_type: :page)
|
50
50
|
@available_actions << action
|
51
51
|
@current_action = action
|
52
|
-
@available_tabs << CmAdmin::Models::Tab.new(tab_name, custom_action, &block)
|
52
|
+
@available_tabs << CmAdmin::Models::Tab.new(tab_name, custom_action, display_if, &block)
|
53
53
|
end
|
54
54
|
yield if block
|
55
55
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module CmAdmin
|
2
2
|
module Models
|
3
3
|
class FormField
|
4
|
-
attr_accessor :field_name, :label, :header, :input_type, :collection, :custom_value, :disabled
|
4
|
+
attr_accessor :field_name, :label, :header, :input_type, :collection, :custom_value, :disabled, :collection_method
|
5
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
|
6
6
|
|
7
7
|
def initialize(field_name, input_type, attributes = {})
|
data/lib/cm_admin/models/tab.rb
CHANGED
@@ -2,11 +2,12 @@ module CmAdmin
|
|
2
2
|
module Models
|
3
3
|
class Tab
|
4
4
|
|
5
|
-
attr_accessor :nav_item_name, :custom_action
|
5
|
+
attr_accessor :nav_item_name, :custom_action, :display_if
|
6
6
|
|
7
|
-
def initialize(nav_item_name, custom_action)
|
7
|
+
def initialize(nav_item_name, custom_action, display_if)
|
8
8
|
@nav_item_name = nav_item_name
|
9
9
|
@custom_action = custom_action
|
10
|
+
@display_if = display_if || lambda { |arg| return true }
|
10
11
|
end
|
11
12
|
end
|
12
13
|
end
|
data/lib/cm_admin/version.rb
CHANGED
@@ -13,9 +13,9 @@ module CmAdmin
|
|
13
13
|
when :string
|
14
14
|
return f.text_field field.field_name, class: "normal-input #{required_class}", disabled: field.disabled, value: value, placeholder: "Enter #{field.field_name.to_s.downcase.gsub('_', ' ')}"
|
15
15
|
when :single_select
|
16
|
-
return f.select field.field_name, options_for_select((field
|
16
|
+
return f.select field.field_name, options_for_select(select_collection_value(field), value), {include_blank: "Select #{field.field_name.to_s.downcase.gsub('_', ' ')}"}, class: "normal-input #{required_class} select-2", disabled: field.disabled
|
17
17
|
when :multi_select
|
18
|
-
return f.select field.field_name, options_for_select((field
|
18
|
+
return f.select field.field_name, options_for_select(select_collection_value(field), value), {include_blank: "Select #{field.field_name.to_s.downcase.gsub('_', ' ')}"}, class: "normal-input #{required_class} select-2", disabled: field.disabled, multiple: true
|
19
19
|
when :date
|
20
20
|
return f.text_field field.field_name, class: "normal-input #{required_class}", disabled: field.disabled, value: value&.strftime('%d-%m-%Y'), placeholder: "Enter #{field.field_name.to_s.downcase.gsub('_', ' ')}", data: { behaviour: 'date-only' }
|
21
21
|
when :date_time
|
@@ -32,6 +32,16 @@ module CmAdmin
|
|
32
32
|
return f.hidden_field field.field_name, value: field.custom_value
|
33
33
|
end
|
34
34
|
end
|
35
|
+
|
36
|
+
def select_collection_value(field)
|
37
|
+
if field.collection_method
|
38
|
+
collection = send(field.collection_method)
|
39
|
+
elsif field.collection
|
40
|
+
collection = field.collection
|
41
|
+
else
|
42
|
+
collection = []
|
43
|
+
end
|
44
|
+
end
|
35
45
|
end
|
36
46
|
end
|
37
47
|
end
|
@@ -38,6 +38,15 @@ module CmAdmin
|
|
38
38
|
|
39
39
|
def set_form_for_fields(resource, available_fields_hash, url, method)
|
40
40
|
form_for(resource, url: url, method: method, html: { class: "cm_#{resource.class.name.downcase}_form" } ) do |f|
|
41
|
+
if params[:referrer]
|
42
|
+
concat f.text_field "referrer", class: "normal-input", hidden: true, value: params[:referrer], name: 'referrer'
|
43
|
+
end
|
44
|
+
if params[:polymorphic_name].present?
|
45
|
+
concat f.text_field params[:polymorphic_name] + '_type', class: "normal-input", hidden: true, value: params[:associated_class].classify
|
46
|
+
concat f.text_field params[:polymorphic_name] + '_id', class: "normal-input", hidden: true, value: params[:associated_id]
|
47
|
+
elsif params[:associated_class] && params[:associated_id]
|
48
|
+
concat f.text_field params[:associated_class] + '_id', class: "normal-input", hidden: true, value: params[:associated_id]
|
49
|
+
end
|
41
50
|
available_fields_hash.each do |key, fields_array|
|
42
51
|
if key == :fields
|
43
52
|
fields_array.each do |field|
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
|
3
|
+
module CmAdmin
|
4
|
+
module Generators
|
5
|
+
class AddAuthenticationGenerator < Rails::Generators::Base
|
6
|
+
source_root File.expand_path('templates', __dir__)
|
7
|
+
|
8
|
+
# This generator is used to add authentication, if no auth system is present.
|
9
|
+
# Adds authentication through devise and sets up the current user.
|
10
|
+
def add_authentication
|
11
|
+
gem "devise"
|
12
|
+
generate "devise:install"
|
13
|
+
model_name = ask("What would you like the user model to be called? [user]")
|
14
|
+
generate "devise", model_name
|
15
|
+
rake "db:migrate"
|
16
|
+
copy_file 'application_controller.rb', 'app/controllers/cm_admin/application_controller.rb'
|
17
|
+
gsub_file 'app/controllers/cm_admin/application_controller.rb', 'authenticate_user', "authenticate_#{model_name}"
|
18
|
+
copy_file 'authentication.rb', 'app/controllers/concerns/authentication.rb'
|
19
|
+
gsub_file 'app/controllers/concerns/authentication.rb', 'current_user', "current_#{model_name}"
|
20
|
+
copy_file 'current.rb', 'app/models/current.rb'
|
21
|
+
inject_into_file "app/models/#{model_name.underscore}.rb", before: "end\n" do <<-'RUBY'
|
22
|
+
# Remove this once role is setup and mentioned in zcm_admin.rb
|
23
|
+
def super_admin?
|
24
|
+
true
|
25
|
+
end
|
26
|
+
RUBY
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
@@ -1 +1 @@
|
|
1
|
-
|
1
|
+
00ac6841e4fa3607e5f705b375dada0dcaf2c84d
|
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.7.
|
4
|
+
version: 0.7.5
|
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-
|
13
|
+
date: 2022-07-05 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: pagy
|
@@ -144,6 +144,7 @@ files:
|
|
144
144
|
- app/assets/stylesheets/cm_admin/scaffold.scss
|
145
145
|
- app/controllers/cm_admin/application_controller.rb
|
146
146
|
- app/controllers/cm_admin/exports_controller.rb
|
147
|
+
- app/controllers/cm_admin/resource_controller.rb
|
147
148
|
- app/controllers/cm_admin/static_controller.rb
|
148
149
|
- app/helpers/cm_admin/application_helper.rb
|
149
150
|
- app/helpers/cm_admin/custom_helper.rb
|
@@ -203,7 +204,6 @@ files:
|
|
203
204
|
- lib/cm_admin/models/blocks.rb
|
204
205
|
- lib/cm_admin/models/cm_show_section.rb
|
205
206
|
- lib/cm_admin/models/column.rb
|
206
|
-
- lib/cm_admin/models/controller_method.rb
|
207
207
|
- lib/cm_admin/models/custom_action.rb
|
208
208
|
- lib/cm_admin/models/dsl_method.rb
|
209
209
|
- lib/cm_admin/models/export.rb
|
@@ -221,11 +221,15 @@ files:
|
|
221
221
|
- lib/cm_admin/view_helpers/manage_column_popup_helper.rb
|
222
222
|
- lib/cm_admin/view_helpers/navigation_helper.rb
|
223
223
|
- lib/cm_admin/view_helpers/page_info_helper.rb
|
224
|
+
- lib/generators/cm_admin/add_authentication_generator.rb
|
224
225
|
- lib/generators/cm_admin/install_generator.rb
|
225
226
|
- lib/generators/cm_admin/policy_generator.rb
|
226
227
|
- lib/generators/cm_admin/templates/actiontext.scss
|
228
|
+
- lib/generators/cm_admin/templates/application_controller.rb
|
227
229
|
- lib/generators/cm_admin/templates/application_policy.rb
|
230
|
+
- lib/generators/cm_admin/templates/authentication.rb
|
228
231
|
- lib/generators/cm_admin/templates/cm_admin_initializer.rb
|
232
|
+
- lib/generators/cm_admin/templates/current.rb
|
229
233
|
- lib/generators/cm_admin/templates/custom.css
|
230
234
|
- lib/generators/cm_admin/templates/custom.js
|
231
235
|
- lib/generators/cm_admin/templates/policy.rb
|
@@ -1,86 +0,0 @@
|
|
1
|
-
module CmAdmin
|
2
|
-
module Models
|
3
|
-
module ControllerMethod
|
4
|
-
extend ActiveSupport::Concern
|
5
|
-
|
6
|
-
def show(params)
|
7
|
-
@current_action = CmAdmin::Models::Action.find_by(self, name: 'show')
|
8
|
-
scoped_model = "CmAdmin::#{self.name}Policy::Scope".constantize.new(Current.user, self.name.constantize).resolve
|
9
|
-
@ar_object = scoped_model.find(params[:id])
|
10
|
-
end
|
11
|
-
|
12
|
-
def index(params)
|
13
|
-
@current_action = CmAdmin::Models::Action.find_by(self, name: 'index')
|
14
|
-
# Based on the params the filter and pagination object to be set
|
15
|
-
@ar_object = filter_by(params, nil, filter_params(params))
|
16
|
-
end
|
17
|
-
|
18
|
-
def new(params)
|
19
|
-
@current_action = CmAdmin::Models::Action.find_by(self, name: 'new')
|
20
|
-
@ar_object = @ar_model.new
|
21
|
-
end
|
22
|
-
|
23
|
-
def edit(params)
|
24
|
-
@current_action = CmAdmin::Models::Action.find_by(self, name: 'edit')
|
25
|
-
@ar_object = @ar_model.name.classify.constantize.find(params[:id])
|
26
|
-
end
|
27
|
-
|
28
|
-
def update(params)
|
29
|
-
@ar_object = @ar_model.name.classify.constantize.find(params[:id])
|
30
|
-
@ar_object.assign_attributes(resource_params(params))
|
31
|
-
@ar_object
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
def create(params)
|
36
|
-
@ar_object = @ar_model.name.classify.constantize.new(resource_params(params))
|
37
|
-
end
|
38
|
-
|
39
|
-
def filter_by(params, records, filter_params={}, sort_params={})
|
40
|
-
filtered_result = OpenStruct.new
|
41
|
-
sort_column = "created_at"
|
42
|
-
sort_direction = %w[asc desc].include?(sort_params[:sort_direction]) ? sort_params[:sort_direction] : "asc"
|
43
|
-
sort_params = {sort_column: sort_column, sort_direction: sort_direction}
|
44
|
-
|
45
|
-
records = "CmAdmin::#{self.name}Policy::Scope".constantize.new(Current.user, self.name.constantize).resolve if records.nil?
|
46
|
-
records = records.order("#{current_action.sort_column} #{current_action.sort_direction}")
|
47
|
-
|
48
|
-
final_data = CmAdmin::Models::Filter.filtered_data(filter_params, records, @filters)
|
49
|
-
pagy, records = pagy(final_data)
|
50
|
-
filtered_result.data = records
|
51
|
-
filtered_result.pagy = pagy
|
52
|
-
# filtered_result.facets = paginate(page, raw_data.size)
|
53
|
-
# filtered_result.sort = sort_params
|
54
|
-
# filtered_result.facets.sort = sort_params
|
55
|
-
return filtered_result
|
56
|
-
end
|
57
|
-
|
58
|
-
def resource_params(params)
|
59
|
-
permittable_fields = @permitted_fields || @ar_model.columns.map(&:name).reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym)
|
60
|
-
permittable_fields += @ar_model.name.constantize.reflect_on_all_associations.map {|x|
|
61
|
-
if x.klass.name == "ActiveStorage::Attachment"
|
62
|
-
if x.class.name.include?('HasOne')
|
63
|
-
x.name
|
64
|
-
elsif x.class.name.include?('HasMany')
|
65
|
-
Hash[x.name.to_s, []]
|
66
|
-
end
|
67
|
-
elsif x.klass.name == "ActionText::RichText"
|
68
|
-
x.name.to_s.gsub('rich_text_', '').to_sym
|
69
|
-
end
|
70
|
-
}.compact
|
71
|
-
nested_tables = self.available_fields[:new].except(:fields).keys
|
72
|
-
nested_tables += self.available_fields[:edit].except(:fields).keys
|
73
|
-
nested_fields = nested_tables.uniq.map {|table|
|
74
|
-
Hash[
|
75
|
-
table.to_s + '_attributes',
|
76
|
-
table.to_s.classify.constantize.columns.map(&:name).reject { |i| CmAdmin::REJECTABLE_FIELDS.include?(i) }.map(&:to_sym) + [:id, :_destroy]
|
77
|
-
]
|
78
|
-
}
|
79
|
-
permittable_fields += nested_fields
|
80
|
-
@ar_model.columns.map { |col| permittable_fields << col.name.split('_cents') if col.name.include?('_cents') }
|
81
|
-
|
82
|
-
params.require(self.name.underscore.to_sym).permit(*permittable_fields)
|
83
|
-
end
|
84
|
-
end
|
85
|
-
end
|
86
|
-
end
|