ab_admin 0.6.1 → 0.7.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (104) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/ab_admin/components/admin_assets.js.coffee +6 -2
  3. data/app/assets/javascripts/ab_admin/components/base_assets.js.coffee +9 -0
  4. data/app/assets/javascripts/ab_admin/components/gmaps.js.coffee +1 -1
  5. data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +6 -0
  6. data/app/assets/javascripts/ab_admin/components/select2_bridge.js.coffee +2 -2
  7. data/app/assets/javascripts/ab_admin/core/batch_actions.js.coffee +52 -12
  8. data/app/assets/javascripts/ab_admin/core/init.js.coffee +2 -0
  9. data/app/assets/javascripts/ab_admin/core/pjax.js.coffee +3 -2
  10. data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +3 -4
  11. data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.scss +4 -0
  12. data/app/assets/stylesheets/ab_admin/components/_colored_tabs.scss +4 -0
  13. data/app/assets/stylesheets/ab_admin/components/_form.scss +36 -3
  14. data/app/controllers/admin/admin_comments_controller.rb +4 -0
  15. data/app/controllers/admin/assets_controller.rb +5 -2
  16. data/app/controllers/admin/base_controller.rb +50 -41
  17. data/app/controllers/admin/locators_controller.rb +1 -1
  18. data/app/controllers/admin/manager_controller.rb +32 -3
  19. data/app/controllers/admin/settings_controller.rb +2 -3
  20. data/app/controllers/admin/static_pages_controller.rb +5 -0
  21. data/app/controllers/admin/structures_controller.rb +10 -4
  22. data/app/controllers/admin/users_controller.rb +9 -2
  23. data/app/views/admin/base/_search_layout.html.slim +0 -1
  24. data/app/views/admin/base/index.html.slim +1 -2
  25. data/app/views/admin/fileupload/_container.html.slim +17 -10
  26. data/app/views/admin/shared/_content_actions.html.slim +18 -6
  27. data/app/views/admin/shared/_locale_tabs.html.slim +3 -3
  28. data/app/views/admin/structures/_form.html.slim +2 -1
  29. data/app/views/layouts/admin/_footer.html.slim +5 -4
  30. data/app/views/layouts/admin/application.html.slim +2 -0
  31. data/config/locales/ru.yml +1 -0
  32. data/config/routes.rb +17 -22
  33. data/lib/ab_admin.rb +11 -1
  34. data/lib/ab_admin/abstract_resource.rb +11 -2
  35. data/lib/ab_admin/carrierwave/base_uploader.rb +45 -25
  36. data/lib/ab_admin/carrierwave/file_size_validator.rb +0 -1
  37. data/lib/ab_admin/carrierwave/glue.rb +2 -4
  38. data/lib/ab_admin/concerns/admin_addition.rb +12 -4
  39. data/lib/ab_admin/concerns/deep_cloneable.rb +0 -1
  40. data/lib/ab_admin/concerns/fileuploads.rb +0 -1
  41. data/lib/ab_admin/concerns/headerable.rb +0 -4
  42. data/lib/ab_admin/concerns/nested_set.rb +2 -3
  43. data/lib/ab_admin/concerns/reloadable.rb +0 -2
  44. data/lib/ab_admin/concerns/silencer.rb +0 -3
  45. data/lib/ab_admin/concerns/utilities.rb +2 -4
  46. data/lib/ab_admin/concerns/validations.rb +1 -1
  47. data/lib/ab_admin/config/base.rb +26 -6
  48. data/lib/ab_admin/controllers/callbacks.rb +6 -6
  49. data/lib/ab_admin/controllers/head_options.rb +0 -1
  50. data/lib/ab_admin/controllers/tree.rb +0 -2
  51. data/lib/ab_admin/core_ext.rb +1 -1
  52. data/lib/ab_admin/core_ext/array.rb +0 -1
  53. data/lib/ab_admin/core_ext/hash.rb +11 -0
  54. data/lib/ab_admin/core_ext/string.rb +0 -1
  55. data/lib/ab_admin/devise.rb +1 -1
  56. data/lib/ab_admin/engine.rb +2 -1
  57. data/lib/ab_admin/hooks/globalize_locale_suffix_accessors.rb +17 -31
  58. data/lib/ab_admin/hooks/will_paginate_no_uri.rb +1 -1
  59. data/lib/ab_admin/i18n_tools/google_translate.rb +0 -1
  60. data/lib/ab_admin/i18n_tools/translate_app.rb +0 -1
  61. data/lib/ab_admin/menu/builder.rb +3 -2
  62. data/lib/ab_admin/menu/group.rb +3 -1
  63. data/lib/ab_admin/models/asset.rb +9 -6
  64. data/lib/ab_admin/models/header.rb +2 -3
  65. data/lib/ab_admin/models/locator.rb +1 -1
  66. data/lib/ab_admin/models/settings.rb +6 -6
  67. data/lib/ab_admin/models/structure.rb +0 -6
  68. data/lib/ab_admin/models/track.rb +12 -3
  69. data/lib/ab_admin/models/type_model.rb +0 -1
  70. data/lib/ab_admin/models/user.rb +0 -1
  71. data/lib/ab_admin/models/validations/all.rb +4 -0
  72. data/lib/ab_admin/models/validations/domain_name_validator.rb +9 -0
  73. data/lib/ab_admin/models/validations/email_validator.rb +9 -0
  74. data/lib/ab_admin/utils.rb +12 -4
  75. data/lib/ab_admin/utils/eval_helpers.rb +1 -1
  76. data/lib/ab_admin/utils/logger.rb +0 -2
  77. data/lib/ab_admin/utils/xls_document.rb +25 -6
  78. data/lib/ab_admin/version.rb +1 -1
  79. data/lib/ab_admin/views/admin_helpers.rb +5 -4
  80. data/lib/ab_admin/views/admin_navigation_helpers.rb +16 -5
  81. data/lib/ab_admin/views/form_builder.rb +41 -10
  82. data/lib/ab_admin/views/helpers.rb +0 -2
  83. data/lib/ab_admin/views/inputs/uploader_input.rb +1 -0
  84. data/lib/ab_admin/views/search_form_builder.rb +33 -7
  85. data/lib/generators/ab_admin/ckeditor_assets/ckeditor_assets_generator.rb +0 -1
  86. data/lib/generators/ab_admin/glob/glob_generator.rb +2 -2
  87. data/lib/generators/ab_admin/glob/templates/migration.erb +1 -1
  88. data/lib/generators/ab_admin/install/install_generator.rb +0 -1
  89. data/lib/generators/ab_admin/install/templates/config/seeds.rb +0 -2
  90. data/lib/generators/ab_admin/install/templates/helpers/admin/structures_helper.rb +1 -4
  91. data/lib/generators/ab_admin/install/templates/models/admin_comment.rb +1 -3
  92. data/lib/generators/ab_admin/install/templates/models/asset.rb +3 -5
  93. data/lib/generators/ab_admin/install/templates/models/header.rb +1 -5
  94. data/lib/generators/ab_admin/install/templates/models/static_page.rb +1 -4
  95. data/lib/generators/ab_admin/install/templates/models/structure.rb +1 -5
  96. data/lib/generators/ab_admin/install/templates/models/track.rb +1 -2
  97. data/lib/generators/ab_admin/install/templates/models/user.rb +1 -9
  98. data/lib/generators/ab_admin/install/templates/uploaders/attachment_file_uploader.rb +1 -1
  99. data/lib/generators/ab_admin/install/templates/uploaders/avatar_uploader.rb +1 -1
  100. data/lib/generators/ab_admin/install/templates/uploaders/picture_uploader.rb +1 -1
  101. data/lib/generators/ab_admin/model/templates/resource.erb +1 -0
  102. data/lib/generators/template.rb +39 -59
  103. metadata +38 -36
  104. data/lib/ab_admin/hooks/active_model_attr_accessible_few_roles.rb +0 -50
@@ -9,7 +9,7 @@ class ::Admin::LocatorsController < ::Admin::BaseController
9
9
  end
10
10
 
11
11
  def update
12
- if Locator.save(@file, {params[:edit_locale_name] => params[:locale_hash]})
12
+ if Locator.save(@file, {params[:edit_locale_name] => params.require(:locale_hash).permit!.to_h})
13
13
  flash[:notice] = I18n.t('flash.admin.locators.updated')
14
14
  redirect_to admin_locators_path
15
15
  else
@@ -18,6 +18,14 @@ class ::Admin::ManagerController < ::Admin::BaseController
18
18
 
19
19
  protected
20
20
 
21
+ def button_scopes
22
+ manager.scopes.map{|scope| [scope.name, scope.options] }
23
+ end
24
+
25
+ def with_scopes(relation)
26
+ manager.scopes.inject(relation) { |result, scope| scope.apply(result, params) }
27
+ end
28
+
21
29
  def begin_of_association_chain
22
30
  parent
23
31
  end
@@ -68,8 +76,9 @@ class ::Admin::ManagerController < ::Admin::BaseController
68
76
  manager.default_action_items_for(action_name.to_sym, for_resource) + manager.action_items_for(action_name.to_sym)
69
77
  end
70
78
 
71
- def apply_batch_action(item, batch_action)
72
- success = call_method_or_proc_on item, manager.batch_action_list.detect{|a| a.name == batch_action }.data, exec: false
79
+ def apply_batch_action(item, batch_action, *batch_params)
80
+ data = manager.batch_action_list.detect{|a| a.name == batch_action }.data
81
+ success = call_method_or_proc_on item, data, exec: false, attrs: batch_params
73
82
  track_action!("batch_#{batch_action}", item) if settings[:history]
74
83
  success
75
84
  end
@@ -115,9 +124,29 @@ class ::Admin::ManagerController < ::Admin::BaseController
115
124
  end
116
125
  end
117
126
 
127
+ def permitted_params
128
+ attrs = case manager.permitted_params
129
+ when Proc then
130
+ instance_exec(&manager.permitted_params)
131
+ else
132
+ Array(manager.permitted_params)
133
+ end
134
+
135
+ resource_params = params[resource_class.model_name.param_key]
136
+ return {} unless resource_params
137
+ if attrs.first == :all
138
+ resource_params.permit!
139
+ else
140
+ attrs = attrs + AbAdmin.default_permitted_params
141
+ resource_params.permit(*attrs)
142
+ end
143
+ end
144
+
118
145
  def preview_resource_path(item)
119
146
  return unless manager.preview_path
120
- manager.preview_path.is_a?(Proc) ? instance_exec(item, &manager.preview_path) : send(manager.preview_path, item)
147
+ I18n.with_locale I18n.default_locale do
148
+ manager.preview_path.is_a?(Proc) ? instance_exec(item, &manager.preview_path) : send(manager.preview_path, item)
149
+ end
121
150
  end
122
151
 
123
152
  def admin_partial_name(builder)
@@ -4,9 +4,9 @@ class ::Admin::SettingsController < ::Admin::BaseController
4
4
  defaults resource_class: Settings
5
5
 
6
6
  def update
7
- Settings.instance.save(params[:settings])
7
+ Settings.instance.save(params.require(:settings).permit!.to_h)
8
8
  Settings.reload_checker.expire
9
- redirect_to :back
9
+ redirect_back fallback_location: admin_root_url
10
10
  end
11
11
 
12
12
  def cache_clear
@@ -31,5 +31,4 @@ class ::Admin::SettingsController < ::Admin::BaseController
31
31
  def resource
32
32
  Settings.instance
33
33
  end
34
-
35
34
  end
@@ -11,4 +11,9 @@ class Admin::StaticPagesController < Admin::BaseController
11
11
  {}
12
12
  end
13
13
 
14
+ def permitted_params
15
+ attrs = [:structure_id, :title, :content, :kind, :is_visible,
16
+ *StaticPage.all_translated_attribute_names, *AbAdmin.default_permitted_params]
17
+ params[:static_page].try!(:permit, *attrs)
18
+ end
14
19
  end
@@ -3,15 +3,12 @@ class Admin::StructuresController < Admin::BaseController
3
3
 
4
4
  load_and_authorize_resource
5
5
 
6
- #has_scope :visible
7
- #has_scope :un_visible
8
-
9
6
  protected
10
7
 
11
8
  def resource_action_items
12
9
  edit_structure = AbAdmin::Config::ActionItem.new({}) { |r| link_to icon('wrench', true), edit_resource_path(r), class: 'btn btn-warning' }
13
10
  edit_static_page = AbAdmin::Config::ActionItem.new({}) do |r|
14
- link_to(icon('pencil', true), edit_structure_record_path(r), class: 'btn btn-primary') if r.structure_type.static_page?
11
+ link_to(icon('pencil', true), edit_structure_record_path(r), class: 'btn btn-primary') if r.structure_type.static_page? || r.structure_type.main?
15
12
  end
16
13
  [edit_static_page, edit_structure, :destroy, :show]
17
14
  end
@@ -23,4 +20,13 @@ class Admin::StructuresController < Admin::BaseController
23
20
  def settings
24
21
  {index_view: 'tree', default_order: 'lft'}
25
22
  end
23
+
24
+ def permitted_params
25
+ attrs = [:structure_type_id, :position_type_id, :parent_id, :title, :redirect_url, :is_visible,
26
+ :structure_type, :position_type,
27
+ *Structure.simple_slug_columns,
28
+ *AbAdmin.default_permitted_params,
29
+ *Structure.all_translated_attribute_names, header_attributes: [:id, *Header.all_translated_attribute_names]]
30
+ params[:structure].try!(:permit, *attrs)
31
+ end
26
32
  end
@@ -3,12 +3,12 @@ class Admin::UsersController < Admin::BaseController
3
3
 
4
4
  def activate
5
5
  resource.activate!
6
- redirect_to :back
6
+ redirect_back fallback_location: admin_users_url
7
7
  end
8
8
 
9
9
  def suspend
10
10
  resource.suspend!
11
- redirect_to :back
11
+ redirect_back fallback_location: admin_users_url
12
12
  end
13
13
 
14
14
  private
@@ -46,4 +46,11 @@ class Admin::UsersController < Admin::BaseController
46
46
  resource
47
47
  end
48
48
 
49
+ def permitted_params
50
+ attrs = [:password, :password_confirmation, :email, :remember_me,
51
+ :login, :first_name, :last_name, :patronymic, :phone, :skype, :web_site, :address, :birthday,
52
+ :time_zone, :locale, :bg_color, :gender, *AbAdmin.default_permitted_params]
53
+ attrs << [:user_role_id] if admin?
54
+ params[:user].try!(:permit, *attrs)
55
+ end
49
56
  end
@@ -1,6 +1,5 @@
1
1
  #toggle_sidebar_off.btn.btn-large = icon('chevron-left')
2
2
  #toggle_sidebar_on.btn.btn-large = icon('chevron-right')
3
- h3= t('admin.search.title')
4
3
  = search_admin_form_for @search, url: collection_path do |f|
5
4
  = render 'search_form', f: f
6
5
  br
@@ -10,8 +10,7 @@
10
10
  .btn-toolbar.pull-right.pjax_links
11
11
  .btn-group
12
12
  - per_page_variants.each do |c|
13
- a.btn.per_page data-val=c href=url_for(params.merge(per_page: c)) class=('active' if c == collection.per_page) = c
13
+ a.btn.per_page data-val=c href=url_for(params_for_links.merge(per_page: c)) class=('active' if c == collection.per_page) = c
14
14
 
15
15
  - if pjax? && flash.present?
16
16
  script type='text/javascript' = render partial: 'admin/shared/flash', formats: :js, local_assigns: {flash: flash}
17
-
@@ -1,15 +1,22 @@
1
1
  .fileupload id=options[:container_id] class=options[:container_class]
2
2
  = options[:error]
3
3
  .fileupload-list.clearfix= render partial: asset_template, collection: assets
4
- .fileupload-upload
5
- .fileupload-button.pull-left
6
- .btn= options[:button_title] || I18n.t("admin.fileupload.button#{'s' if options[:multiple]}")
7
- = file_field_tag 'data', multiple: options[:multiple]
8
- .fileupload-edit-button.btn.pull-left= t('admin.actions.edit.link')
4
+ - unless options[:disabled]
5
+ .fileupload-upload
6
+ .fileupload-button.pull-left
7
+ .btn= options[:button_title] || I18n.t("admin.fileupload.button#{'s' if options[:multiple]}")
8
+ = file_field_tag 'data', multiple: options[:multiple]
9
+ .fileupload-edit-button.btn.pull-left= t('admin.actions.edit.link')
9
10
 
10
- .fileupload-info
11
- - if options[:extensions]
12
- .fileupload-info-extensions= options[:extensions].join(', ')
13
- .fileupload-info-max_size== "#{t('admin.fileupload.max_size')}: <b>#{options[:max_size]}</b> MB"
11
+ .fileupload-info
12
+ - if options[:extensions]
13
+ .fileupload-info-extensions= options[:extensions].join(', ')
14
+ .fileupload-info-max_size== "#{t('admin.fileupload.max_size')}: <b>#{options[:max_size]}</b> MB"
14
15
 
15
- = init_js("new AdminAssets(#{js_options.to_json})")
16
+ javascript:
17
+ if (document.readyState == 'complete') {
18
+ new AdminAssets(#{{js_options.to_json}});
19
+ }
20
+ else {
21
+ $(function(){new AdminAssets(#{{js_options.to_json}});});
22
+ }
@@ -7,12 +7,24 @@
7
7
  ul.dropdown-menu
8
8
  - batch_action_list.each do |batch_action|
9
9
  li
10
- a.batch_action_link href='#' data-action=batch_action.name data-confirm=batch_action.confirm = batch_action.title
10
+ a.batch_action_link(
11
+ href='#'
12
+ data-form=batch_action.form
13
+ data-action=batch_action.name
14
+ data-confirm=batch_action.confirm
15
+ )
16
+ = batch_action.title
11
17
  - unless button_scopes.blank?
12
18
  .btn-group.pjax_links
13
19
  - button_scopes.each do |name, opts|
14
- - active = params[opts[:as]]
15
- a.btn href=url_for(opts[:as] => (active ? nil : 1)) class=('active' if active) = t "admin.scopes.#{name}", default: name
20
+ - param_name = opts[:as] || name
21
+ - active = params[param_name]
22
+ a.btn href=url_for(param_name => (active ? nil : 1)) class=('active' if active)
23
+ = t "admin.scopes.#{name}", default: name.to_s.titleize
24
+ - if opts[:badge]
25
+ - scope_count = resource_class.send(name).count
26
+ - unless scope_count.zero?
27
+ span.badge< class=("badge-#{opts[:badge][:type] || 'important'}") = scope_count
16
28
 
17
29
  a.btn.pull-left#columns_hider_show href="#columns_hider" data-toggle='modal' = t 'admin.columns_hider.button'
18
30
 
@@ -29,9 +41,9 @@
29
41
  .btn-group.downloads
30
42
  = icon('download-alt')
31
43
  /- %w(csv xls json).each do |format|
32
- - %w(csv xls).each do |format|
33
- - next if format == 'xls' && !defined?(Mime::XLSX)
34
- = link_to format, params.merge(per_page: 10_000, format: format), id: "export_#{format}"
44
+ - %w(csv xlsx).each do |format|
45
+ - next if format == 'xlsx' && !Mime[:xlsx]
46
+ = link_to format, params_for_links.merge(per_page: 10_000, format: format), id: "export_#{format}"
35
47
 
36
48
  - if @search && settings[:sort_buttons]
37
49
  .btn-group
@@ -1,8 +1,8 @@
1
1
  .tabbable.locale_tabs
2
2
  ul.nav.nav-tabs
3
- - Globalize.available_locales.each_with_index do |l, i|
3
+ - locales.each_with_index do |l, i|
4
4
  li class=('active' if i.zero?)
5
5
  a data-toggle="tab" href="##{l}" class="ico_#{l}" = t("admin.langs.#{l}", default: l.to_s)
6
6
  .tab-content
7
- - Globalize.available_locales.each_with_index do |l, i|
8
- .tab-pane id=l class="tab_#{l} #{'active' if i.zero?}" = loc_html[l]
7
+ - locales.each_with_index do |l, i|
8
+ .tab-pane id=l class="tab_#{l} #{'active' if i.zero?}" = locale_html[l]
@@ -3,7 +3,8 @@
3
3
  = f.input :title, locale: l
4
4
  = f.input :redirect_url, locale: l, as: :string
5
5
 
6
- = f.input :slug
6
+ - Structure.simple_slug_columns.each do |column|
7
+ = f.input column
7
8
  - if @structure.moveable?
8
9
  = f.input :parent, as: :tree_select
9
10
  = f.input :structure_type_id, collection: StructureType.all
@@ -1,7 +1,8 @@
1
- footer
2
- ' Powered by
3
- a href='https://github.com/leschenko/ab_admin' target='_blank' = "AbAdmin #{AbAdmin::VERSION}"
4
- .muted.footer-notes= AbAdmin.footer_notes
1
+ - if AbAdmin.footer
2
+ footer
3
+ ' Powered by
4
+ a href='https://github.com/leschenko/ab_admin' target='_blank' = "AbAdmin #{AbAdmin::VERSION}"
5
+ .muted.footer-notes= AbAdmin.footer_notes
5
6
 
6
7
  = cache [I18n.locale, 'admin', 'footer'] do
7
8
  = render 'admin/fileupload/asset_templates'
@@ -8,6 +8,8 @@ html id="controller_#{controller_name}"
8
8
  = include_fv
9
9
  = javascript_include_tag 'ab_admin/application'
10
10
  = csrf_meta_tags
11
+ - if AbAdmin.favicon_path
12
+ link rel="icon" type="image/x-icon" href=AbAdmin.favicon_path
11
13
  = yield(:head)
12
14
  body id="action_#{action_name}" class="resource_#{resource_collection_name} #{AbAdmin.body_css_class}"
13
15
  #wrap
@@ -110,6 +110,7 @@ ru:
110
110
  form:
111
111
  cancel: Отмена
112
112
  save: Сохранить
113
+ saving: Сохранение
113
114
  save_and_add_another: Сохранить & новый
114
115
  save_and_edit: Сохранить & редактировать
115
116
  save_and_edit_next: Сохранить и след.
@@ -1,7 +1,6 @@
1
1
  Rails.application.routes.draw do
2
-
3
2
  namespace :admin do
4
- root to: 'dashboards#index'
3
+ root to: 'dashboards#index', as: :root
5
4
  get 'dashboards', as: 'dashboards'
6
5
 
7
6
  resources :structures do
@@ -33,27 +32,23 @@ Rails.application.routes.draw do
33
32
 
34
33
  post 'translate' => AbAdmin::I18nTools::TranslateApp
35
34
 
36
- controller 'manager', constraints: {format: /(html|js|json|xml|csv|xls|xlsx)/} do
37
- scope '(/:parent_resource/:parent_resource_id)/:model_name' do
38
- get '/new', action: :new, as: 'new'
39
- post '/batch', action: :batch, as: 'batch'
40
- post '/rebuild', action: :rebuild, as: 'rebuild'
41
- match '/custom_action', action: :custom_action, as: 'collection_action', via: :all
42
-
43
- scope ':id' do
44
- get '/edit', action: :edit, as: 'edit'
45
- get '/history', action: :history, as: 'history'
46
- match '/custom_action', action: :custom_action, as: 'member_action', via: :all
47
- get '/', action: :show, as: 'show'
48
- patch '/', action: :update, as: 'update'
49
- delete '/', action: :destroy, as: 'destroy'
50
- end
51
-
52
- get '/', action: :index, as: 'index'
53
- post '/', action: :create, as: 'create'
35
+ scope '(/:parent_resource/:parent_resource_id)/:model_name', controller: 'manager', constraints: {format: /(html|js|json|xml|csv|xls|xlsx)/} do
36
+ get '/new', action: :new, as: 'new'
37
+ post '/batch', action: :batch, as: 'batch'
38
+ post '/rebuild', action: :rebuild, as: 'rebuild'
39
+ match '/custom_action', action: :custom_action, as: 'collection_action', via: :all
40
+
41
+ scope ':id' do
42
+ get '/edit', action: :edit, as: 'edit'
43
+ get '/history', action: :history, as: 'history'
44
+ match '/custom_action', action: :custom_action, as: 'member_action', via: :all
45
+ get '/', action: :show, as: 'show'
46
+ patch '/', action: :update, as: 'update'
47
+ delete '/', action: :destroy, as: 'destroy'
54
48
  end
55
- end
56
49
 
50
+ get '/', action: :index, as: 'index'
51
+ post '/', action: :create, as: 'create'
52
+ end
57
53
  end
58
-
59
54
  end
@@ -8,6 +8,9 @@ require 'ab_admin/core_ext'
8
8
  require 'ab_admin/engine'
9
9
 
10
10
  module AbAdmin
11
+ DOMAINNAME_REGEXP = /\A(?:[0-9a-z]\.|[0-9a-z][0-9a-z\-]*[0-9a-z]+\.)+[a-z]{2,6}\z/
12
+ EMAIL_REGEXP = /\A[_A-Za-z0-9\-\+]+(?:\.[_A-Za-z0-9\-\+]+)*@(?:[0-9a-z]\.|[0-9a-z][0-9a-z\-]*[0-9a-z]+\.)+[a-z]{2,6}\z/
13
+
11
14
  autoload :Utils, 'ab_admin/utils'
12
15
  autoload :Devise, 'ab_admin/devise'
13
16
  autoload :AbstractResource, 'ab_admin/abstract_resource'
@@ -134,6 +137,8 @@ module AbAdmin
134
137
 
135
138
  mattr_accessor :body_css_class
136
139
 
140
+ mattr_accessor :favicon_path
141
+
137
142
  mattr_accessor :devise_layout
138
143
  @@devise_layout = 'admin/devise'
139
144
 
@@ -152,6 +157,9 @@ module AbAdmin
152
157
  mattr_accessor :test_settings
153
158
  @@test_settings = {}
154
159
 
160
+ mattr_accessor :footer
161
+ @@footer = true
162
+
155
163
  mattr_accessor :footer_notes
156
164
 
157
165
  mattr_accessor :default_url_options
@@ -179,12 +187,14 @@ module AbAdmin
179
187
  mattr_accessor :per_page_variants
180
188
  @@per_page_variants = [50, 100, 500, 1000]
181
189
 
190
+ mattr_accessor :default_permitted_params
191
+ @@default_permitted_params = [:fileupload_guid]
192
+
182
193
  extend Utils
183
194
 
184
195
  def self.setup
185
196
  yield self
186
197
  end
187
-
188
198
  end
189
199
 
190
200
 
@@ -8,7 +8,7 @@ module AbAdmin
8
8
 
9
9
  attr_accessor :model, :table, :search, :export, :form, :modal_form, :show, :preview_path, :actions, :custom_settings,
10
10
  :batch_action_list, :action_items, :disabled_action_items, :resource_action_items, :tree_node_renderer,
11
- :parent_resources, :custom_actions
11
+ :parent_resources, :custom_actions, :permitted_params, :scopes
12
12
 
13
13
  def initialize
14
14
  @actions = ACTIONS
@@ -20,6 +20,7 @@ module AbAdmin
20
20
  @action_items_for = {}
21
21
  @parent_resources = []
22
22
  @custom_actions = []
23
+ @scopes = []
23
24
  @model = self.class.name.sub('AbAdmin', '').safe_constantize
24
25
  add_admin_addition_to_model
25
26
  end
@@ -58,6 +59,10 @@ module AbAdmin
58
59
  instance.preview_path = block_given? ? block : value
59
60
  end
60
61
 
62
+ def permitted_params(*values, &block)
63
+ instance.permitted_params = block_given? ? block : values
64
+ end
65
+
61
66
  def actions(*actions_to_keep)
62
67
  instance.actions = begin
63
68
  options = actions_to_keep.extract_options!
@@ -123,6 +128,10 @@ module AbAdmin
123
128
  def collection_action(name, options={}, &block)
124
129
  instance.custom_actions << AbAdmin::Config::CustomAction.new(name, options.merge(collection: true), &block)
125
130
  end
131
+
132
+ def scope(name, options={}, &block)
133
+ instance.scopes << AbAdmin::Config::Scope.new(name, options, &block)
134
+ end
126
135
  end
127
136
 
128
137
  def export
@@ -164,4 +173,4 @@ module AbAdmin
164
173
  model.included_modules.include?(module_constant)
165
174
  end
166
175
  end
167
- end
176
+ end
@@ -1,18 +1,16 @@
1
- # encoding: utf-8
2
1
  require 'mime/types'
3
2
  require 'mini_magick'
4
3
  require 'carrierwave/processing/mini_magick'
5
- require 'carrierwave/processing/mime_types'
6
4
 
7
5
  module AbAdmin
8
6
  module CarrierWave
9
7
  class BaseUploader < ::CarrierWave::Uploader::Base
10
8
  include ::CarrierWave::MiniMagick
11
- include ::CarrierWave::MimeTypes
12
9
  include AbAdmin::Utils::EvalHelpers
13
10
 
14
- class_attribute :transliterate
11
+ class_attribute :transliterate, :human_filenames
15
12
  self.transliterate = true
13
+ self.human_filenames = true
16
14
 
17
15
  attr_accessor :internal_identifier
18
16
 
@@ -20,8 +18,6 @@ module AbAdmin
20
18
 
21
19
  storage :file
22
20
 
23
- process :set_content_type
24
-
25
21
  with_options if: :image? do |img|
26
22
  img.process :strip
27
23
  img.process cropper: lambda { |model| model.cropper_geometry }
@@ -30,19 +26,35 @@ module AbAdmin
30
26
 
31
27
  process :set_model_info
32
28
 
29
+ def strict_filename(for_file=filename)
30
+ "#{version_name || secure_token}#{File.extname(for_file).downcase}"
31
+ end
32
+
33
33
  def save_original_name(file)
34
34
  model.original_name ||= file.original_filename if file.respond_to?(:original_filename)
35
35
  end
36
36
 
37
+ def base_filename_part
38
+ if version_name
39
+ version_name.to_s.start_with?('retina_') ? "#{version_name.to_s.sub(/^retina_/, '')}@2x" : version_name.to_s
40
+ else
41
+ secure_token
42
+ end
43
+ end
44
+
37
45
  def full_filename(for_file=filename)
38
- ext = File.extname(for_file)
46
+ human_filenames ? human_full_filename(for_file) : strict_filename(for_file)
47
+ end
48
+
49
+ def human_full_filename(for_file=filename)
50
+ ext = File.extname(for_file).downcase
39
51
  human_filename_part = for_file.chomp(ext)
40
- tech_filename_part = "#{version_name || secure_token}#{ext}"
52
+ tech_filename_part = "#{base_filename_part}#{ext}"
41
53
  human_filename_part == secure_token ? tech_filename_part : "#{human_filename_part}_#{tech_filename_part}"
42
54
  end
43
55
 
44
56
  def full_original_filename
45
- "#{version_name || secure_token}#{File.extname(store_filename)}"
57
+ "#{base_filename_part}#{File.extname(store_filename)}"
46
58
  end
47
59
 
48
60
  # use secure token in the filename for non processed image
@@ -60,7 +72,7 @@ module AbAdmin
60
72
  alias_method :store_filename, :filename
61
73
 
62
74
  def filename
63
- internal_identifier || model.send("#{mounted_as}_file_name") || (store_filename && "#{secure_token}#{File.extname(store_filename)}")
75
+ internal_identifier || model.send("#{mounted_as}_file_name") || (store_filename && "#{secure_token}#{File.extname(store_filename).downcase}")
64
76
  end
65
77
 
66
78
  def write_internal_identifier(internal_identifier)
@@ -73,34 +85,42 @@ module AbAdmin
73
85
  def model_filename(base_filename, record)
74
86
  custom_file_name = model.build_filename(base_filename, record)
75
87
  return unless custom_file_name
76
- normalize_filename(custom_file_name) + File.extname(base_filename)
88
+ normalize_filename(custom_file_name) + File.extname(base_filename).downcase
77
89
  end
78
90
 
79
91
  def normalize_filename(raw_filename)
80
- I18n.transliterate(raw_filename).parameterize('_').gsub(/[\-_]+/, '_').downcase
92
+ parameterize_args = ActiveSupport::VERSION::MAJOR > 4 ? {separator: '_'} : '_'
93
+ I18n.transliterate(raw_filename).parameterize(parameterize_args).gsub(/[\-_]+/, '_').downcase
81
94
  end
82
95
 
83
96
  # rename files via move
84
97
  def rename_via_move(new_file_name)
85
- dir = File.dirname(path)
86
-
87
- moves = []
88
- versions.values.unshift(self).each do |v|
89
- from_path = File.join(dir, v.full_filename)
90
- to_path = File.join(dir, v.full_filename(new_file_name))
91
- return false if from_path == to_path || !File.exists?(from_path)
92
- moves << [from_path, to_path]
98
+ if human_filenames
99
+ dir = File.dirname(path)
100
+
101
+ moves = []
102
+ versions.values.unshift(self).each do |v|
103
+ from_path = File.join(dir, v.full_filename)
104
+ to_path = File.join(dir, v.full_filename(new_file_name))
105
+ next if from_path == to_path || !File.exists?(from_path)
106
+ moves << [from_path, to_path]
107
+ end
108
+ moves.each { |move| FileUtils.mv(*move) }
93
109
  end
94
- moves.each { |move| FileUtils.mv(*move) }
95
110
 
96
111
  write_internal_identifier new_file_name
97
112
  model.send("write_#{mounted_as}_identifier")
98
- retrieve_from_store!(new_file_name)
113
+ retrieve_from_store!(new_file_name) if human_filenames
114
+
99
115
  new_file_name
100
116
  end
101
117
 
102
118
  private :write_internal_identifier, :store_filename, :model_filename
103
119
 
120
+ def rmagick_included?
121
+ self.class.included_modules.map(&:to_s).include?('CarrierWave::RMagick')
122
+ end
123
+
104
124
  # prevent large number of subdirectories
105
125
  def store_dir
106
126
  str_id = model.id.to_s.rjust(4, '0')
@@ -126,7 +146,7 @@ module AbAdmin
126
146
 
127
147
  unless percentage.blank?
128
148
  manipulate! do |img|
129
- img.quality(percentage.to_s)
149
+ img.quality percentage.to_s
130
150
  img = yield(img) if block_given?
131
151
  img
132
152
  end
@@ -141,7 +161,7 @@ module AbAdmin
141
161
 
142
162
  unless degrees.blank?
143
163
  manipulate! do |img|
144
- img.rotate(degrees.to_s)
164
+ rmagick_included? ? img.rotate!(degrees.to_i) : img.rotate(degrees.to_s)
145
165
  img = yield(img) if block_given?
146
166
  img
147
167
  end
@@ -179,7 +199,7 @@ module AbAdmin
179
199
  end
180
200
 
181
201
  def image?(new_file = nil)
182
- (file || new_file).content_type.include? 'image'
202
+ AbAdmin.image_types.include?((file || new_file).content_type)
183
203
  end
184
204
 
185
205
  def dimensions