ab_admin 0.9.0 → 0.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +28 -24
- data/app/assets/javascripts/ab_admin/core/batch_actions.js.coffee +1 -1
- data/app/assets/javascripts/ab_admin/core/init.js.coffee +1 -0
- data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +21 -1
- data/app/assets/javascripts/ab_admin/core/utils.js.coffee +8 -0
- data/app/assets/javascripts/ab_admin/inputs/datetime_input.js.coffee +1 -0
- data/app/assets/javascripts/ab_admin/main.js +1 -2
- data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.scss +44 -23
- data/app/assets/stylesheets/ab_admin/components/_colored_tabs.scss +1 -1
- data/app/assets/stylesheets/ab_admin/components/_form.scss +3 -1
- data/app/assets/stylesheets/ab_admin/components/_navigation.scss +7 -2
- data/app/assets/stylesheets/ab_admin/components/_table_view.scss +75 -9
- data/app/assets/stylesheets/ab_admin/components/_tooltip.scss +1 -0
- data/app/assets/stylesheets/ab_admin/main.scss +1 -1
- data/app/controllers/admin/assets_controller.rb +1 -1
- data/app/controllers/admin/base_controller.rb +87 -107
- data/app/controllers/admin/manager_controller.rb +17 -47
- data/app/views/ab_admin/devise/sessions/new.html.slim +2 -0
- data/app/views/admin/assets/batch_edit.html.slim +2 -1
- data/app/views/admin/base/_search_layout.html.slim +1 -1
- data/app/views/admin/base/create.js.erb +1 -1
- data/app/views/admin/base/edit.js.erb +1 -1
- data/app/views/admin/base/new.js.erb +1 -1
- data/app/views/admin/base/update.js.erb +3 -3
- data/app/views/admin/manager/_show_table.html.slim +1 -1
- data/app/views/admin/manager/_stats.html.slim +4 -0
- data/app/views/admin/manager/_table.html.slim +6 -3
- data/app/views/admin/shared/_content_actions.html.slim +22 -15
- data/app/views/admin/shared/_save_buttons.html.slim +10 -1
- data/app/views/admin/users/_form.html.slim +2 -2
- data/config/locales/en.yml +8 -13
- data/config/locales/it.yml +1 -0
- data/db/migrate/20130101000001_create_users.rb +1 -4
- data/db/migrate/20130101000003_create_assets.rb +1 -1
- data/db/migrate/20130101000004_create_headers.rb +5 -5
- data/db/migrate/20130101000005_create_static_pages.rb +2 -5
- data/db/migrate/20130101000006_create_structures.rb +1 -1
- data/db/migrate/20130101000007_base_translations.rb +43 -12
- data/db/migrate/20130101000008_create_admin_comments.rb +2 -7
- data/db/migrate/20130101000009_create_tracks.rb +4 -8
- data/lib/ab_admin/abstract_resource.rb +6 -5
- data/lib/ab_admin/carrierwave/base_uploader.rb +87 -74
- data/lib/ab_admin/carrierwave/glue.rb +0 -5
- data/lib/ab_admin/concerns/admin_addition.rb +19 -1
- data/lib/ab_admin/concerns/utilities.rb +1 -1
- data/lib/ab_admin/config/base.rb +20 -4
- data/lib/ab_admin/core_ext/array.rb +0 -5
- data/lib/ab_admin/core_ext/string.rb +1 -6
- data/lib/ab_admin/devise.rb +7 -0
- data/lib/ab_admin/engine.rb +1 -1
- data/lib/ab_admin/hooks/ckeditor_lazy.rb +13 -0
- data/lib/ab_admin/menu/base_group.rb +0 -1
- data/lib/ab_admin/menu/group.rb +2 -4
- data/lib/ab_admin/menu/item.rb +4 -8
- data/lib/ab_admin/models/asset.rb +7 -10
- data/lib/ab_admin/models/locator.rb +1 -1
- data/lib/ab_admin/models/settings.rb +2 -2
- data/lib/ab_admin/models/structure.rb +3 -3
- data/lib/ab_admin/models/track.rb +15 -3
- data/lib/ab_admin/utils/csv_document.rb +4 -4
- data/lib/ab_admin/utils/eval_helpers.rb +0 -16
- data/lib/ab_admin/utils/logger.rb +12 -2
- data/lib/ab_admin/utils/mysql.rb +2 -3
- data/lib/ab_admin/utils/xls_document.rb +1 -3
- data/lib/ab_admin/utils.rb +0 -5
- data/lib/ab_admin/version.rb +1 -1
- data/lib/ab_admin/views/admin_helpers.rb +33 -16
- data/lib/ab_admin/views/admin_navigation_helpers.rb +12 -9
- data/lib/ab_admin/views/inputs/ckeditor_input.rb +1 -5
- data/lib/ab_admin/views/manager_helpers.rb +9 -3
- data/lib/ab_admin/views/search_form_builder.rb +12 -12
- data/lib/ab_admin.rb +13 -2
- data/lib/generators/ab_admin/install/templates/models/user.rb +1 -2
- data/lib/generators/ab_admin/install/templates/uploaders/attachment_file_uploader.rb +1 -1
- data/lib/generators/ab_admin/install/templates/uploaders/avatar_uploader.rb +1 -1
- data/lib/generators/ab_admin/install/templates/uploaders/picture_uploader.rb +16 -3
- data/lib/generators/ab_admin/resource/resource_generator.rb +0 -4
- data/lib/generators/ab_admin/resource/templates/controller.erb +0 -7
- data/lib/tasks/assets.rake +5 -5
- metadata +28 -26
@@ -1,44 +1,39 @@
|
|
1
1
|
class Admin::BaseController < ::InheritedResources::Base
|
2
|
-
use Rack::Pjax, only: :index
|
3
|
-
|
4
|
-
layout :set_layout
|
5
|
-
|
6
2
|
include AbAdmin::Controllers::Fv
|
7
3
|
include AbAdmin::Controllers::Callbacks
|
8
4
|
|
9
|
-
|
5
|
+
class_attribute :export_builder, :batch_actions, :button_scopes, instance_reader: true, instance_writer: false
|
6
|
+
attr_reader :settings
|
10
7
|
|
11
|
-
before_action :authenticate_user!, :require_admin_access, :build_settings, :set_user_vars
|
8
|
+
before_action :authenticate_user!, :require_admin_access, :manager, :build_settings, :set_user_vars
|
12
9
|
before_action :add_breadcrumbs, :set_title, unless: :xhr?
|
10
|
+
before_action :preflight_batch_action, only: :batch
|
13
11
|
|
14
|
-
|
15
|
-
|
16
|
-
defaults finder: :friendly_find
|
17
|
-
|
18
|
-
has_scope :by_ids, type: :array
|
19
|
-
|
20
|
-
helper_method :admin?, :moderator?
|
21
|
-
|
22
|
-
attr_reader :settings
|
23
|
-
helper_method :button_scopes, :collection_action?, :action_items, :resource_action_items, :query_params,
|
24
|
-
:preview_resource_path, :get_subject, :settings, :batch_action_list, :tree_node_renderer,
|
12
|
+
helper_method :admin?, :moderator?, :button_scopes, :collection_action?, :action_items, :resource_action_items, :query_params,
|
13
|
+
:settings, :batch_actions, :tree_node_renderer,
|
25
14
|
:pjax?, :xhr?, :params_for_links, :resource_list_id, :ransack_collection, :search_collection
|
26
15
|
|
16
|
+
define_admin_callbacks :save, :create
|
17
|
+
use Rack::Pjax, only: :index
|
18
|
+
defaults finder: :friendly_find
|
27
19
|
rescue_from ::CanCan::AccessDenied, with: :render_unauthorized
|
20
|
+
layout :set_layout
|
28
21
|
|
29
22
|
def index
|
30
23
|
super do |format|
|
31
24
|
format.js { render layout: false }
|
32
|
-
|
33
|
-
|
34
|
-
doc = AbAdmin::Utils::CsvDocument.new(collection, export_options)
|
35
|
-
send_data(doc.render(self, locale: params[:locale]), filename: doc.filename, type: Mime[:csv], disposition: 'attachment')
|
36
|
-
end
|
37
|
-
if Mime[:xlsx]
|
38
|
-
format.xlsx do
|
25
|
+
if settings[:export]
|
26
|
+
format.csv do
|
39
27
|
authorize! :export, resource_class
|
40
|
-
doc = AbAdmin::Utils::
|
41
|
-
send_data(doc.render(self, locale: params[:locale]), filename: doc.filename, type: Mime[:
|
28
|
+
doc = AbAdmin::Utils::CsvDocument.new(collection, export_options)
|
29
|
+
send_data(doc.render(self, locale: params[:locale]), filename: doc.filename, type: Mime[:csv], disposition: 'attachment')
|
30
|
+
end
|
31
|
+
if Mime[:xlsx]
|
32
|
+
format.xlsx do
|
33
|
+
authorize! :export, resource_class
|
34
|
+
doc = AbAdmin::Utils::XlsDocument.new(collection, export_options)
|
35
|
+
send_data(doc.render(self, locale: params[:locale]), filename: doc.filename, type: Mime[:xlsx], disposition: 'attachment')
|
36
|
+
end
|
42
37
|
end
|
43
38
|
end
|
44
39
|
end
|
@@ -49,10 +44,15 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
49
44
|
success.html { redirect_to redirect_to_on_success }
|
50
45
|
success.js { render layout: false }
|
51
46
|
failure.js { render :new, layout: false }
|
47
|
+
unless respond_to_format?(:json)
|
48
|
+
success.json { head :no_content }
|
49
|
+
failure.json { render json: {errors: resource.errors}, status: :unprocessable_entity }
|
50
|
+
end
|
52
51
|
end
|
53
52
|
end
|
54
53
|
|
55
54
|
def update
|
55
|
+
resource.last_updated_timestamp = params[:last_updated_timestamp].to_i if settings[:safe_save] && !params[:_force_save] && params[:last_updated_timestamp]
|
56
56
|
update! do |success, failure|
|
57
57
|
success.html { redirect_to redirect_to_on_success }
|
58
58
|
failure.html { render :edit }
|
@@ -60,7 +60,7 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
60
60
|
failure.js { render :edit, layout: false }
|
61
61
|
unless respond_to_format?(:json)
|
62
62
|
success.json { head :no_content }
|
63
|
-
failure.json {
|
63
|
+
failure.json { render json: {errors: resource.errors}, status: :unprocessable_entity }
|
64
64
|
end
|
65
65
|
end
|
66
66
|
end
|
@@ -91,32 +91,26 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def batch
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
if batch_action.to_s.end_with?('_collection')
|
98
|
-
count = collection.size
|
99
|
-
resource_class.public_send(batch_action, collection, *[params[:batch_params]].compact)
|
100
|
-
if @settings[:history]
|
101
|
-
if Object.const_defined?('ActiveRecord::Import') && Track.respond_to?(:import)
|
102
|
-
tracks = collection.map { |item| track_action("batch_#{batch_action}", item) }
|
103
|
-
Track.import_from_batch_collection_action(tracks)
|
104
|
-
else
|
105
|
-
collection.each { |item| track_action!("batch_#{batch_action}", item) }
|
106
|
-
end
|
107
|
-
end
|
108
|
-
else
|
109
|
-
count = collection.inject(0) { |c, item| apply_batch_action(item, batch_action, *[params[:batch_params]].compact) ? c + 1 : c }
|
110
|
-
end
|
111
|
-
batch_action_name = I18n.t("admin.actions.batch_#{batch_action}.title", default: batch_action.to_s.humanize)
|
112
|
-
flash[:success] = I18n.t('admin.batch_actions.status', count: count, action: batch_action_name)
|
113
|
-
else
|
114
|
-
raise CanCan::AccessDenied
|
115
|
-
end
|
94
|
+
batch_action = batch_actions.detect{|a| a.name == params[:batch_action].to_sym }
|
95
|
+
count = collection.inject(0) { |c, item| apply_batch_action(item, batch_action, *params[:batch_params].presence) ? c + 1 : c }
|
96
|
+
flash[:success] = I18n.t('admin.batch_actions.status', count: count, action: batch_action.title)
|
116
97
|
redirect_to_back_or_root
|
117
98
|
end
|
118
99
|
|
119
|
-
|
100
|
+
private
|
101
|
+
|
102
|
+
def manager
|
103
|
+
end
|
104
|
+
|
105
|
+
def set_layout
|
106
|
+
pjax? ? false : 'admin/application'
|
107
|
+
end
|
108
|
+
|
109
|
+
def preflight_batch_action
|
110
|
+
batch_action = params[:batch_action].to_sym
|
111
|
+
head :unprocessable_entity unless allow_batch_action?(batch_action) && params[:q].try!(:[], :id_in).present?
|
112
|
+
raise CanCan::AccessDenied unless collection.all?{|item| can?(batch_action, item) }
|
113
|
+
end
|
120
114
|
|
121
115
|
def build_resource_params
|
122
116
|
permitted_params || params[resource_class.model_name.param_key]
|
@@ -133,22 +127,26 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
133
127
|
def default_url_options
|
134
128
|
options = {format: nil}
|
135
129
|
options.update instance_exec(&AbAdmin.default_url_options) if AbAdmin.default_url_options
|
136
|
-
options.update instance_exec(&@settings[:default_url_options]) if @settings[:default_url_options]
|
130
|
+
options.update instance_exec(&@settings[:default_url_options]) if @settings && @settings[:default_url_options]
|
137
131
|
options
|
138
132
|
end
|
139
133
|
|
134
|
+
def self.batch_action(name, options={}, &block)
|
135
|
+
if options
|
136
|
+
self.batch_actions << AbAdmin::Config::BatchAction.new(name.to_sym, options, &block)
|
137
|
+
else
|
138
|
+
self.batch_actions.reject!{|a| a.name == name.to_sym }
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
140
142
|
def apply_batch_action(item, batch_action, *batch_params)
|
141
|
-
success = item.
|
142
|
-
track_action!("batch_#{batch_action}", item) if
|
143
|
+
success = batch_action.data.is_a?(Symbol) ? item.public_send(batch_action.data, *batch_params) : batch_action.data.call(item)
|
144
|
+
track_action!("batch_#{batch_action.name}", item) if settings[:history]
|
143
145
|
success
|
144
146
|
end
|
145
147
|
|
146
148
|
def allow_batch_action?(batch_action)
|
147
|
-
|
148
|
-
end
|
149
|
-
|
150
|
-
def redirect_to_back_or_root
|
151
|
-
redirect_back fallback_location: admin_root_path
|
149
|
+
batch_actions.detect { |a| a.name == batch_action }
|
152
150
|
end
|
153
151
|
|
154
152
|
def track_action(key=nil, item=nil)
|
@@ -159,19 +157,6 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
159
157
|
track_action(*args).save!
|
160
158
|
end
|
161
159
|
|
162
|
-
def batch_action_list
|
163
|
-
self.class.batch_action_list ||= begin
|
164
|
-
resource_class.batch_actions.map do |a|
|
165
|
-
opts = a == :destroy ? {confirm: I18n.t('admin.delete_confirmation')} : {}
|
166
|
-
if a.is_a?(Hash)
|
167
|
-
opts.merge!(a.except(:name))
|
168
|
-
a = a[:name]
|
169
|
-
end
|
170
|
-
AbAdmin::Config::BatchAction.new(a, opts)
|
171
|
-
end
|
172
|
-
end
|
173
|
-
end
|
174
|
-
|
175
160
|
def self.inherited(base)
|
176
161
|
super
|
177
162
|
base.class_eval do
|
@@ -179,6 +164,8 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
179
164
|
before_save :bind_current_updater
|
180
165
|
before_save :track_current_action
|
181
166
|
end
|
167
|
+
base.button_scopes = []
|
168
|
+
base.batch_actions = [AbAdmin::Config::BatchAction.new(:destroy, confirm: I18n.t('admin.delete_confirmation'))]
|
182
169
|
end
|
183
170
|
|
184
171
|
def track_current_action(*)
|
@@ -202,10 +189,6 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
202
189
|
export_builder.render_options
|
203
190
|
end
|
204
191
|
|
205
|
-
def preview_resource_path(item)
|
206
|
-
nil
|
207
|
-
end
|
208
|
-
|
209
192
|
def custom_settings
|
210
193
|
{}
|
211
194
|
end
|
@@ -219,7 +202,8 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
219
202
|
@settings[:per_page] ||= per_page
|
220
203
|
@settings[:per_page_variants] ||= @settings[:per_page_variants].find_all{|n| n <= @settings[:max_per_page] }
|
221
204
|
@settings[:sidebar] = true unless @settings.key?(:sidebar)
|
222
|
-
@settings[:pagination] = @settings[:pagination_index_views].include?(@settings[:current_index_view])
|
205
|
+
@settings[:pagination] = @settings[:pagination_index_views].include?(@settings[:current_index_view]) unless @settings.key?(:pagination)
|
206
|
+
@settings[:order] = active_scopes.filter_map{|sc| sc.options[:default_order] }.first || @settings[:default_order] || ('id desc' unless @settings[:current_index_view] == :tree)
|
223
207
|
end
|
224
208
|
@settings[:well] = (collection_action? || %w(show history).include?(action_name)) && @settings[:current_index_view] != :tree unless @settings.key?(:well)
|
225
209
|
end
|
@@ -243,19 +227,6 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
243
227
|
@settings[:collection_actions].include?(action_name)
|
244
228
|
end
|
245
229
|
|
246
|
-
def self.scope(name, options={}, &block)
|
247
|
-
has_scope name, options.without(:badge, :if), &block
|
248
|
-
options[:badge] = {} if options[:badge] && !options[:badge].is_a?(Hash)
|
249
|
-
options[:block] = block
|
250
|
-
self.button_scopes ||= []
|
251
|
-
self.button_scopes << [name, options]
|
252
|
-
end
|
253
|
-
|
254
|
-
def button_scopes
|
255
|
-
self.class.button_scopes ||= self.class.scopes_configuration.except(:by_ids).find_all{|_, s| s[:type] == :boolean }
|
256
|
-
self.class.button_scopes.to_h
|
257
|
-
end
|
258
|
-
|
259
230
|
def add_breadcrumbs
|
260
231
|
@breadcrumbs = []
|
261
232
|
if parent?
|
@@ -306,18 +277,28 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
306
277
|
end
|
307
278
|
|
308
279
|
def query_params
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
280
|
+
@query_params ||= begin
|
281
|
+
query = params[:q].try! {|q| q.permit!.to_h} || {}
|
282
|
+
query[:s] ||= @settings[:order]
|
283
|
+
query.reverse_merge!(@settings[:default_q].to_h{ [_1.to_s, _2.to_s] }) if @settings[:default_q] && !params[:q]
|
284
|
+
query.reject_blank
|
285
|
+
end
|
286
|
+
end
|
287
|
+
|
288
|
+
def self.scope(name, options={}, &block)
|
289
|
+
self.button_scopes << ::AbAdmin::Config::Scope.new(name, options, &block)
|
290
|
+
end
|
291
|
+
|
292
|
+
def active_scopes
|
293
|
+
button_scopes.find_all{|scope| params[scope.name].present? }
|
313
294
|
end
|
314
295
|
|
315
296
|
def with_scopes(relation)
|
316
|
-
relation
|
297
|
+
active_scopes.inject(relation) { |result, scope| scope.apply(self, result) }
|
317
298
|
end
|
318
299
|
|
319
|
-
def
|
320
|
-
|
300
|
+
def redirect_to_back_or_root
|
301
|
+
redirect_back fallback_location: admin_root_path, turbolinks: false
|
321
302
|
end
|
322
303
|
|
323
304
|
def back_or_collection
|
@@ -382,7 +363,7 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
382
363
|
end
|
383
364
|
|
384
365
|
def require_admin_access
|
385
|
-
raise CanCan::AccessDenied unless current_user
|
366
|
+
raise CanCan::AccessDenied unless current_user&.admin_access?
|
386
367
|
end
|
387
368
|
|
388
369
|
def bind_current_user(*)
|
@@ -393,13 +374,14 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
393
374
|
resource.updater_id = current_user.id if !@settings[:skip_bind_current_updater] && resource.respond_to?(:updater_id)
|
394
375
|
end
|
395
376
|
|
396
|
-
def
|
397
|
-
|
377
|
+
def authenticate_user!
|
378
|
+
Rails.logger.debug "Redirect unauthorized user"
|
379
|
+
super
|
398
380
|
end
|
399
381
|
|
400
382
|
def render_unauthorized(exception)
|
401
|
-
Rails.logger.debug "Access denied on #{exception.action} #{exception.subject.inspect}, user: #{current_user
|
402
|
-
|
383
|
+
Rails.logger.debug "Access denied on #{exception.action} #{exception.subject.inspect}, user: #{current_user&.id}"
|
384
|
+
render_not_found and return unless AbAdmin.render_unauthorized
|
403
385
|
if pjax?
|
404
386
|
render partial: 'admin/shared/flash', locals: {flash: {alert: exception.message}}
|
405
387
|
elsif request.format.try(:html?)
|
@@ -409,11 +391,11 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
409
391
|
end
|
410
392
|
end
|
411
393
|
|
412
|
-
def
|
413
|
-
if
|
414
|
-
|
394
|
+
def render_not_found
|
395
|
+
if request.format.try(:html?)
|
396
|
+
render file: Rails.root.join('public/404.html'), layout: false, status: :not_found
|
415
397
|
else
|
416
|
-
|
398
|
+
head :not_found
|
417
399
|
end
|
418
400
|
end
|
419
401
|
|
@@ -421,8 +403,6 @@ class Admin::BaseController < ::InheritedResources::Base
|
|
421
403
|
"list_#{resource_instance_name}_#{resource.id}"
|
422
404
|
end
|
423
405
|
|
424
|
-
private
|
425
|
-
|
426
406
|
def per_page
|
427
407
|
request_per_page = (params[:per_page].presence || cookies[:pp].presence).to_i.nonzero?
|
428
408
|
params[:per_page] = [request_per_page || @settings[:view_default_per_page][@settings[:current_index_view]], @settings[:max_per_page]].min
|
@@ -1,9 +1,6 @@
|
|
1
1
|
class ::Admin::ManagerController < ::Admin::BaseController
|
2
|
-
include AbAdmin::Utils::EvalHelpers
|
3
2
|
include AbAdmin::Controllers::Tree
|
4
3
|
|
5
|
-
prepend_before_action :manager
|
6
|
-
|
7
4
|
load_and_authorize_resource
|
8
5
|
|
9
6
|
helper_method :manager, :admin_partial_name, :history_resource_path, :fetch_admin_template
|
@@ -11,23 +8,19 @@ class ::Admin::ManagerController < ::Admin::BaseController
|
|
11
8
|
def custom_action
|
12
9
|
custom_action = manager.custom_action_for(params[:custom_action], self)
|
13
10
|
if custom_action.options[:method] && custom_action.options[:method] != request.method_symbol
|
14
|
-
raise ActionController::RoutingError.new("AbAdmin custom action
|
11
|
+
raise ActionController::RoutingError.new("AbAdmin custom action #{custom_action.options[:method].to_s.upcase} #{params[:custom_action]} not allowed for #{request.method_symbol} method")
|
15
12
|
end
|
16
13
|
instance_exec(&custom_action.data)
|
17
14
|
end
|
18
15
|
|
19
|
-
|
16
|
+
private
|
20
17
|
|
21
18
|
def button_scopes
|
22
|
-
manager.scopes
|
23
|
-
end
|
24
|
-
|
25
|
-
def with_scopes(relation)
|
26
|
-
scopes_to_apply.inject(relation) { |result, scope| scope.apply(result, params) }
|
19
|
+
manager.scopes
|
27
20
|
end
|
28
21
|
|
29
|
-
def
|
30
|
-
manager.
|
22
|
+
def batch_actions
|
23
|
+
manager.batch_actions
|
31
24
|
end
|
32
25
|
|
33
26
|
def begin_of_association_chain
|
@@ -80,21 +73,6 @@ class ::Admin::ManagerController < ::Admin::BaseController
|
|
80
73
|
manager.default_action_items_for(action_name.to_sym, for_resource) + manager.action_items_for(action_name.to_sym)
|
81
74
|
end
|
82
75
|
|
83
|
-
def apply_batch_action(item, batch_action, *batch_params)
|
84
|
-
data = manager.batch_action_list.detect{|a| a.name == batch_action }.data
|
85
|
-
success = call_method_or_proc_on item, data, exec: false, attrs: batch_params
|
86
|
-
track_action!("batch_#{batch_action}", item) if settings[:history]
|
87
|
-
success
|
88
|
-
end
|
89
|
-
|
90
|
-
def allow_batch_action?(batch_action)
|
91
|
-
manager.batch_action_list.detect { |a| a.name == batch_action }
|
92
|
-
end
|
93
|
-
|
94
|
-
def batch_action_list
|
95
|
-
manager.batch_action_list
|
96
|
-
end
|
97
|
-
|
98
76
|
def custom_settings
|
99
77
|
manager.custom_settings || {}
|
100
78
|
end
|
@@ -107,13 +85,11 @@ class ::Admin::ManagerController < ::Admin::BaseController
|
|
107
85
|
@manager ||= begin
|
108
86
|
manager_class_name = "AbAdmin#{resource_class.name}"
|
109
87
|
manager_instance = manager_class_name.constantize.instance
|
110
|
-
unless manager_instance.allow_action?(action_name)
|
111
|
-
raise ActionController::RoutingError.new("AbAdmin action #{action_name} for #{resource_class.name} not found")
|
112
|
-
end
|
88
|
+
raise ActionController::RoutingError.new("AbAdmin action #{action_name} not found") unless manager_instance.allow_action?(action_name)
|
113
89
|
manager_instance
|
114
90
|
rescue NameError => e
|
115
|
-
if e.message.include?(manager_class_name)
|
116
|
-
raise ActionController::RoutingError.new("AbAdmin
|
91
|
+
if e.message.include?("uninitialized constant #{manager_class_name}")
|
92
|
+
raise ActionController::RoutingError.new("AbAdmin manager for #{resource_class.name} not found (#{e.message})")
|
117
93
|
else
|
118
94
|
raise
|
119
95
|
end
|
@@ -122,9 +98,14 @@ class ::Admin::ManagerController < ::Admin::BaseController
|
|
122
98
|
|
123
99
|
def resource_class
|
124
100
|
@model ||= begin
|
125
|
-
params[:model_name].classify
|
126
|
-
|
127
|
-
|
101
|
+
model_name = params[:model_name].classify
|
102
|
+
model_name.constantize
|
103
|
+
rescue NameError => e
|
104
|
+
if e.message.include?("uninitialized constant #{model_name}")
|
105
|
+
raise ActionController::RoutingError.new("AbAdmin model #{model_name} not found (#{e.message})")
|
106
|
+
else
|
107
|
+
raise
|
108
|
+
end
|
128
109
|
end
|
129
110
|
end
|
130
111
|
|
@@ -140,19 +121,8 @@ class ::Admin::ManagerController < ::Admin::BaseController
|
|
140
121
|
end
|
141
122
|
end
|
142
123
|
|
143
|
-
def preview_resource_path(item)
|
144
|
-
return unless manager.preview_path
|
145
|
-
return if manager.preview_path[:options][:if] && !call_method_or_proc_on(item, manager.preview_path[:options][:if])
|
146
|
-
I18n.with_locale I18n.default_locale do
|
147
|
-
manager.preview_path[:value].is_a?(Proc) ? instance_exec(item, &manager.preview_path[:value]) : send(manager.preview_path[:value], item)
|
148
|
-
end
|
149
|
-
end
|
150
|
-
|
151
124
|
def admin_partial_name(builder)
|
152
|
-
builder.partial ||=
|
153
|
-
#if template_exists?(builder.partial_name, "admin/#{resource_collection_name}", true)
|
154
|
-
fetch_admin_template(builder.partial_name, true)
|
155
|
-
end
|
125
|
+
builder.partial ||= fetch_admin_template(builder.partial_name, true)
|
156
126
|
end
|
157
127
|
|
158
128
|
def fetch_admin_template(template_name, partial=false)
|
@@ -3,6 +3,8 @@
|
|
3
3
|
.form-inputs
|
4
4
|
= f.input :email, required: false, autofocus: true
|
5
5
|
= f.input :password, required: false
|
6
|
+
- if devise_mapping.try(:two_factor_authenticatable?)
|
7
|
+
= f.input :otp_attempt, required: false
|
6
8
|
= f.input :remember_me, as: :boolean, wrapper: :default if devise_mapping.rememberable?
|
7
9
|
= f.button :submit, t('admin.auth.sessions.button', default: 'Sign in'), class: 'btn-primary btn-large'
|
8
10
|
br
|
@@ -7,7 +7,8 @@
|
|
7
7
|
a.thumbnail href=asset.url target='_blank' = image_tag(asset.thumb_url)
|
8
8
|
.span8
|
9
9
|
- if first_locale == l
|
10
|
-
|
10
|
+
.muted= asset.original_name
|
11
|
+
div= text_field :data, :human_filename, index: asset.id, value: asset.human_filename, placeholder: Asset.han(:data_file_name), style: 'width: 95%;'
|
11
12
|
- [:alt, :name].each do |attr|
|
12
13
|
- loc_attr = "#{attr}_#{l}"
|
13
14
|
p= text_field :data, loc_attr, index: asset.id, value: asset.send(loc_attr), placeholder: Asset.han(attr), style: 'width: 95%;'
|
@@ -5,7 +5,7 @@
|
|
5
5
|
div
|
6
6
|
= f.submit t('admin.search.submit'), class: 'btn btn-success search-submit'
|
7
7
|
button.js-search-cancel.btn.search-cancel= icon('remove')
|
8
|
-
= render 'search_form', f: f
|
8
|
+
= render settings[:search_form_name] || 'search_form', f: f
|
9
9
|
div
|
10
10
|
= f.submit t('admin.search.submit'), class: 'btn btn-success search-submit'
|
11
11
|
button.js-search-cancel.btn.search-cancel= icon('remove')
|
@@ -10,7 +10,7 @@
|
|
10
10
|
$('#<%= form_wrap_id %>').remove();
|
11
11
|
$('#list tbody:first').prepend('<%= j html %>');
|
12
12
|
$(document).trigger('admin:list_init');
|
13
|
-
$('#<%= dom_id(resource, 'list') %>').addClass('
|
13
|
+
$('#<%= dom_id(resource, 'list') %>').addClass('bg-lemon');
|
14
14
|
<% end %>
|
15
15
|
|
16
16
|
window.ab_admin_last_created = <%= raw resource.for_input_token.to_json %>;
|
@@ -10,7 +10,7 @@
|
|
10
10
|
%>
|
11
11
|
$('#<%= form_wrap_id %>').remove();
|
12
12
|
$('#<%= el_id %>').after('<%= j html %>');
|
13
|
-
$('#<%= form_wrap_id %> td
|
13
|
+
$('#<%= form_wrap_id %> > td').attr('colspan', $('#list > thead > tr:first th').length);
|
14
14
|
$('#<%= form_wrap_id %> form').trigger('admin:form_init');
|
15
15
|
$('#<%= el_id %>').scrollToEl();
|
16
16
|
<% end %>
|
@@ -9,7 +9,7 @@
|
|
9
9
|
%>
|
10
10
|
$('#<%= form_wrap_id %>').remove();
|
11
11
|
$('#list tbody:first').prepend('<%= j html %>');
|
12
|
-
$('#<%= form_wrap_id %> td
|
12
|
+
$('#<%= form_wrap_id %> > td').attr('colspan', $('#list > thead > tr > th').length);
|
13
13
|
$('#<%= form_wrap_id %> form').trigger('admin:form_init');
|
14
14
|
<% end %>
|
15
15
|
|
@@ -1,8 +1,9 @@
|
|
1
|
+
<%= render 'admin/shared/flash' %>
|
2
|
+
|
1
3
|
<% if params[:flash] %>
|
2
4
|
flash("<%= t("flash.admin.actions.#{action_name}.notice", resource_name: resource_class.model_name.human(count: 1)) %>")
|
3
5
|
<% end %>
|
4
6
|
|
5
|
-
|
6
7
|
<% unless params[:modal] %>
|
7
8
|
<%
|
8
9
|
form_wrap_id = dom_id(resource, 'list_edit')
|
@@ -12,8 +13,7 @@
|
|
12
13
|
$('#<%= dom_id(resource, 'list') %>').replaceWith('<%= j html %>');
|
13
14
|
var $el = $('#<%= dom_id(resource, 'list') %>');
|
14
15
|
$(document).trigger('admin:list_init');
|
15
|
-
|
16
|
-
$el.scrollToEl();
|
16
|
+
$el.addClass('bg-lemon');
|
17
17
|
<% end %>
|
18
18
|
|
19
19
|
window.ab_admin_last_updated = <%= raw resource.for_input_token.to_json %>;
|
@@ -19,12 +19,15 @@
|
|
19
19
|
tbody
|
20
20
|
- is_edit_link = manager.actions.include?(:edit)
|
21
21
|
- collection.each do |item|
|
22
|
-
tr id=dom_id(item, 'list') class=(
|
22
|
+
tr id=dom_id(item, 'list') class=method_or_proc_on(table_builder.row_html_class, item)
|
23
23
|
= batch_action_item(item)
|
24
|
-
td
|
24
|
+
td
|
25
|
+
= id_link(item, edit: is_edit_link)
|
26
|
+
- if settings[:id_column_with_created_at]
|
27
|
+
div: i= l(item.created_at, format: AbAdmin.datetime_format)
|
25
28
|
= item_index_actions_panel(item)
|
26
29
|
- table_builder.fields.each do |field|
|
27
|
-
td class=
|
30
|
+
td class=field.options[:cell_html_class]
|
28
31
|
- field_content = table_item_field(item, field)
|
29
32
|
- if field_content.present? && field.options[:copy_button]
|
30
33
|
- field_id = dom_id(item, field.name)
|
@@ -5,22 +5,21 @@
|
|
5
5
|
= t 'admin.batch_actions.title'
|
6
6
|
span.caret
|
7
7
|
ul.dropdown-menu
|
8
|
-
-
|
8
|
+
- batch_actions.each do |ba|
|
9
9
|
li: a.batch_action_link href='#' data-form=ba.form data-action=ba.name data-confirm=ba.confirm = ba.title
|
10
10
|
- if settings[:button_scopes] && button_scopes.present?
|
11
11
|
.btn-group
|
12
|
-
- button_scopes.each do |
|
13
|
-
- next
|
14
|
-
-
|
15
|
-
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
-
|
21
|
-
- scope_count = scope.send(*[opts[:badge][:value_type] || :count, opts[:badge][:column]].compact)
|
12
|
+
- button_scopes.each do |s|
|
13
|
+
- next unless option_conditions_met?(s.options)
|
14
|
+
- active = params[s.param_name]
|
15
|
+
- url = url_for(s.param_name => (active ? nil : 1), index_view: params[:index_view])
|
16
|
+
a.btn href=url title=s.options[:title] class=[s.options[:class], ('active' if active), ('tool tool-bottom' if s.options[:title])]
|
17
|
+
= s.options[:label] || s.options[:title] || t("admin.scopes.#{s.name}", default: s.name.to_s.titleize)
|
18
|
+
- if s.options[:badge]
|
19
|
+
- scope = s.apply(self, resource_class.accessible_by(current_ability))
|
20
|
+
- scope_count = scope.send(*[s.options[:badge][:value_type] || :count, s.options[:badge][:column]].compact)
|
22
21
|
- unless scope_count.zero?
|
23
|
-
span.badge< class=("badge-#{
|
22
|
+
span.badge< class=("badge-#{s.options.dig(:badge, :type) || 'important'} #{'pulse' if s.options.dig(:badge, :pulse)}") = scope_count
|
24
23
|
|
25
24
|
- if settings[:current_index_view] == :table
|
26
25
|
.btn-group#columns_hider_wrap
|
@@ -38,7 +37,7 @@
|
|
38
37
|
- settings[:index_views].each do |index_view|
|
39
38
|
= index_view_link(index_view)
|
40
39
|
|
41
|
-
- if can?(:export, resource_class)
|
40
|
+
- if settings[:export] && can?(:export, resource_class)
|
42
41
|
.btn-group.downloads
|
43
42
|
= icon('download-alt')
|
44
43
|
- %w(csv xlsx).each do |format|
|
@@ -56,6 +55,14 @@
|
|
56
55
|
.label> class=(ag[:css] || 'label-success')
|
57
56
|
=> ag[:label] || "#{ag[:column].to_s.humanize}:"
|
58
57
|
- if !ag[:type] || ag[:type] == :sum
|
59
|
-
= search_collection.distinct(false).sum(ag[:column])
|
58
|
+
- res = search_collection.unscope(:includes).distinct(false).sum(ag[:column])
|
59
|
+
= number_with_delimiter(res.round(2), delimiter: ' ') if res
|
60
60
|
- elsif ag[:type] == :average
|
61
|
-
= search_collection.average(ag[:column])
|
61
|
+
- res = search_collection.unscope(:includes).average(ag[:column])
|
62
|
+
= number_with_delimiter(res.round(2), delimiter: ' ') if res
|
63
|
+
- elsif ag[:type] == :pct
|
64
|
+
- sc_count = search_collection.count
|
65
|
+
- if sc_count.zero?
|
66
|
+
| 0%
|
67
|
+
- else
|
68
|
+
= "#{(search_collection.where.not(ag[:column] => nil).count.to_f / search_collection.count * 100).try!(:round, 2)}%"
|
@@ -1,10 +1,19 @@
|
|
1
1
|
- return_to = params[:return_to].presence || request.referer || collection_path
|
2
|
-
- return_to = "#{return_to}##{dom_id(resource, 'list')}" if resource.persisted?
|
2
|
+
- return_to = "#{return_to.split('#', 2).first}##{dom_id(resource, 'list')}" if resource.persisted?
|
3
3
|
input type='hidden' name='return_to' value=return_to
|
4
|
+
- if settings[:safe_save] && resource.updated_at
|
5
|
+
input type='hidden' name='last_updated_timestamp' value=(resource.last_updated_timestamp || resource.updated_timestamp.to_i)
|
4
6
|
.form-actions
|
5
7
|
button.btn.btn-primary type="submit" name="_save" data-disable-with=t('admin.form.save')
|
6
8
|
= icon('ok', true)
|
7
9
|
= t('admin.form.save')
|
10
|
+
- if resource.errors.of_kind?(:base, :changed)
|
11
|
+
a.btn href=edit_resource_path(resource, return_to: params[:return_to])
|
12
|
+
= icon('repeat')
|
13
|
+
= t('admin.form.refresh')
|
14
|
+
button.btn.btn-warning type="submit" name="_force_save" data-disable-with='Force'
|
15
|
+
= icon('fire', true)
|
16
|
+
= t('admin.form.force_save')
|
8
17
|
span.extra_buttons
|
9
18
|
- unless resource.new_record?
|
10
19
|
span.next_prev_buttons
|
@@ -18,8 +18,8 @@
|
|
18
18
|
= f.input :locale, collection: AbAdmin.translated_locales
|
19
19
|
= f.input :bg_color, as: :color
|
20
20
|
|
21
|
-
= f.input :password, input_html: {autocomplete: '
|
22
|
-
= f.input :password_confirmation, input_html: {autocomplete: '
|
21
|
+
= f.input :password, input_html: {autocomplete: 'new-password'}
|
22
|
+
= f.input :password_confirmation, input_html: {autocomplete: 'new-password'}
|
23
23
|
|
24
24
|
= f.input :avatar, as: :uploader, edit_meta: true
|
25
25
|
|