ab_admin 0.8.2 → 0.8.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (67) hide show
  1. checksums.yaml +5 -5
  2. data/app/assets/javascripts/ab_admin/core/init.js.coffee +0 -1
  3. data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +8 -0
  4. data/app/assets/javascripts/ab_admin/main.js +0 -1
  5. data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.scss +1 -1
  6. data/app/assets/stylesheets/ab_admin/components/_form.scss +23 -2
  7. data/app/assets/stylesheets/ab_admin/components/_table_view.scss +1 -0
  8. data/app/controllers/admin/assets_controller.rb +1 -1
  9. data/app/controllers/admin/locators_controller.rb +2 -4
  10. data/app/controllers/admin/manager_controller.rb +2 -1
  11. data/app/controllers/admin/settings_controller.rb +2 -2
  12. data/app/views/admin/assets/batch_update.js.erb +4 -0
  13. data/app/views/admin/base/new.js.erb +1 -1
  14. data/app/views/admin/fileupload/_asset_templates.html.slim +1 -1
  15. data/app/views/admin/fileupload/_image.html.slim +2 -1
  16. data/app/views/admin/locators/show.html.slim +6 -9
  17. data/app/views/admin/manager/_table.html.slim +7 -10
  18. data/app/views/admin/shared/_content_actions.html.slim +1 -1
  19. data/app/views/admin/shared/_main_menu.html.slim +1 -1
  20. data/app/views/layouts/admin/_footer.html.slim +6 -6
  21. data/app/views/layouts/admin/devise.html.slim +2 -3
  22. data/config/locales/en.yml +5 -5
  23. data/lib/ab_admin/abstract_resource.rb +2 -2
  24. data/lib/ab_admin/carrierwave/base_uploader.rb +6 -7
  25. data/lib/ab_admin/concerns/admin_addition.rb +1 -1
  26. data/lib/ab_admin/concerns/headerable.rb +4 -0
  27. data/lib/ab_admin/config/base.rb +2 -3
  28. data/lib/ab_admin/i18n_tools/google_translate.rb +1 -1
  29. data/lib/ab_admin/models/admin_comment.rb +1 -1
  30. data/lib/ab_admin/models/asset.rb +4 -3
  31. data/lib/ab_admin/models/locator.rb +18 -5
  32. data/lib/ab_admin/models/settings.rb +37 -42
  33. data/lib/ab_admin/models/user.rb +2 -2
  34. data/lib/ab_admin/utils.rb +1 -2
  35. data/lib/ab_admin/utils/eval_helpers.rb +5 -3
  36. data/lib/ab_admin/version.rb +1 -1
  37. data/lib/ab_admin/views/admin_helpers.rb +48 -30
  38. data/lib/ab_admin/views/admin_navigation_helpers.rb +6 -7
  39. data/lib/ab_admin/views/inputs/uploader_input.rb +2 -2
  40. data/lib/generators/ab_admin/install/templates/config/ab_admin.rb.erb +0 -2
  41. data/lib/generators/ab_admin/install/templates/models/settings.rb +1 -5
  42. data/lib/generators/ab_admin/model/templates/resource.erb +1 -3
  43. data/lib/generators/template.rb +0 -2
  44. metadata +4 -27
  45. data/app/assets/images/admin/flags/toremove/b_de.png +0 -0
  46. data/app/assets/images/admin/flags/toremove/b_en.png +0 -0
  47. data/app/assets/images/admin/flags/toremove/b_es.png +0 -0
  48. data/app/assets/images/admin/flags/toremove/b_fr.png +0 -0
  49. data/app/assets/images/admin/flags/toremove/b_it.png +0 -0
  50. data/app/assets/images/admin/flags/toremove/b_ru.png +0 -0
  51. data/app/assets/images/admin/flags/toremove/b_uk.png +0 -0
  52. data/app/assets/images/admin/flags/toremove/flag_de.gif +0 -0
  53. data/app/assets/images/admin/flags/toremove/flag_de_nonact.gif +0 -0
  54. data/app/assets/images/admin/flags/toremove/flag_en.gif +0 -0
  55. data/app/assets/images/admin/flags/toremove/flag_en_nonact.gif +0 -0
  56. data/app/assets/images/admin/flags/toremove/flag_es.gif +0 -0
  57. data/app/assets/images/admin/flags/toremove/flag_es_nonact.gif +0 -0
  58. data/app/assets/images/admin/flags/toremove/flag_fr.gif +0 -0
  59. data/app/assets/images/admin/flags/toremove/flag_fr_nonact.gif +0 -0
  60. data/app/assets/images/admin/flags/toremove/flag_it.gif +0 -0
  61. data/app/assets/images/admin/flags/toremove/flag_it_nonact.gif +0 -0
  62. data/app/assets/images/admin/flags/toremove/flag_ru.gif +0 -0
  63. data/app/assets/images/admin/flags/toremove/flag_ru_nonact.gif +0 -0
  64. data/app/assets/images/admin/flags/toremove/flag_uk.gif +0 -0
  65. data/app/assets/images/admin/flags/toremove/flag_uk_nonact.gif +0 -0
  66. data/app/assets/javascripts/ab_admin/components/init_nested_filelds.js.coffee +0 -7
  67. data/app/assets/javascripts/ab_admin/core/deprecated_utils.js.coffee +0 -44
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4e8d999fb88464fad70ad946040526c58aa3e514
4
- data.tar.gz: f8f9cdc1adeea88a740ebc3fb5266cf7a24b639b
2
+ SHA256:
3
+ metadata.gz: 43ed57227cecaa2f87430c9c4d91b091a481d63a7c114f11815475d035d7c0fa
4
+ data.tar.gz: 3c468bae1894700743f5c78d9c833c57ece9638179174294e6a1ba90dd2cae54
5
5
  SHA512:
6
- metadata.gz: 6228321150b29065d1e7059ad3e0b9af0bf2ff4290f70f213a9594d4c3f5187b2b8318749cd8670f001c9a1f718c429b579fc67cfe38fdc32f745d686bc99d28
7
- data.tar.gz: d19c4790fca2cd080baf4520b4c8b08ab543fdad6959db138ef986b48bdd36d460ab5f1af6809e84ad3893ab1d20ddc1a98162ffc6a26ac2a86e1d3dcae34da8
6
+ metadata.gz: f172fa06ba23701ba8d0849267642bbe51485951aed25d1f686a342b7b770d5983b0387886cc544c83269e653d026e31cae9fb3b2eacd40c2c5e402b2c032b3d
7
+ data.tar.gz: c90de19869723ace5d640bfc0b426cbfa7982f1555312dee5b990cf8a523bb09d4468c7fb1fd3297d5181987a892897638e8411690a06474539de0bb42e687fc
@@ -50,7 +50,6 @@ $ ->
50
50
 
51
51
  initFancySelect()
52
52
  initNestedFields()
53
- initNestedFields()
54
53
  inputSetToggle()
55
54
  inputBtnClose()
56
55
  initEditableBool()
@@ -82,3 +82,11 @@ window.initEditableBool = ->
82
82
  success: ->
83
83
  $wrap.addClass('success')
84
84
  $el.attr('disabled', null)
85
+
86
+ window.initNestedFields = (opts={}) ->
87
+ $(document).on 'nested:fieldAdded', 'form.simple_form', (e) =>
88
+ window.locale_tabs?.initHandlers() unless opts.skip_tabs
89
+ window.initFancySelect() unless opts.skip_fancy
90
+ window.initPickers() unless opts.skip_pickers
91
+ window.initEditor() unless opts.skip_editor
92
+ opts.callback.call(e) if opts.callback
@@ -27,7 +27,6 @@
27
27
  //= require ab_admin/components/admin_assets
28
28
  //= require ab_admin/components/gmaps
29
29
  //= require ab_admin/components/in_place_edit
30
- //= require ab_admin/components/init_nested_filelds
31
30
  //= require ab_admin/components/hotkeys
32
31
  //= require ab_admin/inputs/datetime_input
33
32
 
@@ -42,7 +42,7 @@ img {
42
42
  }
43
43
 
44
44
  .well-small {
45
- margin-bottom: 15px;
45
+ margin-bottom: 10px;
46
46
  }
47
47
 
48
48
  .dropdown .caret {
@@ -55,9 +55,9 @@ input[type="color"],
55
55
  .form-actions {
56
56
  position: fixed;
57
57
  bottom: -20px;
58
- left: 0px;
58
+ left: 0;
59
59
  border-radius: 10px;
60
- padding: 10px;
60
+ padding: 5px;
61
61
  z-index: 4;
62
62
  .btn {
63
63
  margin-right: 5px;
@@ -178,6 +178,21 @@ textarea.text {
178
178
  margin-left: 10px;
179
179
  }
180
180
 
181
+ .select2-container-multi .select2-choices {
182
+ background-color: #fff;
183
+ border: 1px solid #ccc;
184
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
185
+ transition: border linear 0.2s, box-shadow linear 0.2s;
186
+ border-radius: 4px;
187
+ background-image: none;
188
+ }
189
+ .select2-container-multi .select2-choices .select2-search-choice {
190
+ margin: 3px;
191
+ }
192
+ .select2-container-multi .select2-choices .select2-search-field input {
193
+ padding: 3px;
194
+ }
195
+
181
196
  .label.control-label.label-reset {
182
197
  display: block;
183
198
  }
@@ -191,7 +206,13 @@ textarea.text {
191
206
  padding: 2px 4px 2px 6px;
192
207
  border-radius: 5px;
193
208
  input.js-auto-submit-checkbox[type='checkbox'] {
209
+ width: auto;
194
210
  margin: 0;
211
+ line-height: normal;
212
+ vertical-align: text-bottom;
213
+ }
214
+ label {
215
+ margin-bottom: 0;
195
216
  }
196
217
  &.success {
197
218
  background-color: #dff0d8;
@@ -124,6 +124,7 @@ table.index_table {
124
124
  }
125
125
  }
126
126
 
127
+ tr.test-hover > td > .actions_panel-wrap_outer > .actions_panel-wrap_inner,
127
128
  tr:hover > td > .actions_panel-wrap_outer > .actions_panel-wrap_inner {
128
129
  display: block;
129
130
  }
@@ -35,7 +35,7 @@ class Admin::AssetsController < ApplicationController
35
35
 
36
36
  def batch_update
37
37
  Asset.update(params[:data].keys, params[:data].values)
38
- head :ok
38
+ @assets = Asset.find(params[:data].keys)
39
39
  end
40
40
 
41
41
  def rotate
@@ -6,15 +6,13 @@ class ::Admin::LocatorsController < ::Admin::BaseController
6
6
 
7
7
  def export
8
8
  authorize! :export, resource_class
9
- locales = I18n.available_locales & params[:locales].split(',').map(&:to_sym) if params[:locales].present?
10
- keys = Locator.export_csv(*params[:keys].to_s.split(','), locales: locales)
9
+ keys = Locator.export_csv(*params[:keys].to_s.split(','), locales: params[:locales], files: params[:files])
11
10
  send_data(keys, filename: "locales_#{Time.now.strftime('%Y_%m_%d')}.csv", type: Mime[:csv], disposition: 'attachment')
12
11
  end
13
12
 
14
13
  def import
15
14
  if params[:csv_file].present?
16
- locales = I18n.available_locales & params[:locales].split(',').map(&:to_sym) if params[:locales].present?
17
- Locator.import_csv(params[:csv_file].read, locales: locales)
15
+ Locator.import_csv(params[:csv_file].read, locales: params[:locales])
18
16
  flash[:notice] = 'File imported'
19
17
  else
20
18
  flash[:error] = 'Missing or invalid csv file'
@@ -142,8 +142,9 @@ class ::Admin::ManagerController < ::Admin::BaseController
142
142
 
143
143
  def preview_resource_path(item)
144
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])
145
146
  I18n.with_locale I18n.default_locale do
146
- manager.preview_path.is_a?(Proc) ? instance_exec(item, &manager.preview_path) : send(manager.preview_path, item)
147
+ manager.preview_path[:value].is_a?(Proc) ? instance_exec(item, &manager.preview_path[:value]) : send(manager.preview_path[:value], item)
147
148
  end
148
149
  end
149
150
 
@@ -4,7 +4,7 @@ class ::Admin::SettingsController < ::Admin::BaseController
4
4
  defaults resource_class: Settings
5
5
 
6
6
  def update
7
- Settings.instance.save(params.require(:settings).permit!.to_h)
7
+ Settings.update(params.require(:settings).permit!.to_h)
8
8
  Settings.reload_checker.expire
9
9
  redirect_back fallback_location: admin_root_url
10
10
  end
@@ -21,7 +21,7 @@ class ::Admin::SettingsController < ::Admin::BaseController
21
21
  end
22
22
 
23
23
  def collection
24
- @settings ||= Settings.instance.editable
24
+ @collection ||= Settings.editable_data
25
25
  end
26
26
 
27
27
  def collection_path
@@ -0,0 +1,4 @@
1
+ <% @assets.each do |asset| %>
2
+ uploader = $('#asset_<%= asset.id %>').closest('.fileupload').data('assets');
3
+ $('#asset_<%= asset.id %>').replaceWith(uploader.assetHtml(<%== asset.to_json(root: false) %>));
4
+ <% end %>
@@ -8,7 +8,7 @@
8
8
  html = %[<tr id="#{form_wrap_id}" class="warning list_edit"><td>#{render('form')}</td></tr>].html_safe
9
9
  %>
10
10
  $('#<%= form_wrap_id %>').remove();
11
- $('#list tbody').prepend('<%= j html %>');
11
+ $('#list tbody:first').prepend('<%= j html %>');
12
12
  $('#<%= form_wrap_id %> td:first').attr('colspan', $('#list tr:first th').length);
13
13
  $('#<%= form_wrap_id %> form').trigger('admin:form_init');
14
14
  <% end %>
@@ -6,7 +6,7 @@ script#image_template type='text/x-handlebars-template'
6
6
  .crop_image title=t('admin.fileupload.crop') = icon('resize-full', true)
7
7
  .rotate_image title=t('admin.fileupload.rotate') = icon('repeat', true)
8
8
  a.fileupload-file.fancybox href='{{url}}' rel='fancybox'
9
- img src='{{thumb_url}}' title='{{filename}}'
9
+ img src='{{thumb_url}}' title='{{name}}' alt="{{alt}}"
10
10
 
11
11
 
12
12
  script#file_template type='text/x-handlebars-template'
@@ -5,4 +5,5 @@
5
5
  .crop_image title=t('admin.fileupload.crop') = icon('resize-full', true)
6
6
  .rotate_image title=t('admin.fileupload.rotate') = icon('repeat', true)
7
7
  a.fileupload-file.fancybox href=image.url rel='fancybox'
8
- img src=image.thumb_url title=image.filename
8
+ - I18n.with_locale(image.assetable.try(:locale)) do
9
+ img src=image.thumb_url title=image.name alt=image.alt
@@ -15,20 +15,17 @@ table.table.table-striped.table-bordered style='width: 1050px;'
15
15
  hr
16
16
 
17
17
  = form_tag export_admin_locators_path, method: :get do
18
- input.input-xxlarge> type='text' name='keys' placeholder='Keys comma separated'
19
- br
20
- input.input-medium.fancy_select> type='text' name='locales' placeholder='Locales, all by default' data-tags=I18n.available_locales.to_json
21
- br
22
- br
18
+ p= select_tag :files, options_for_select(@files.map{|path| File.basename(path) }), multiple: true, class: 'fancy_select input-xxlarge', placeholder: 'Filenames comma separated, all by default'
19
+ p
20
+ input.input-xxlarge> type='text' name='keys' placeholder='Keys comma separated, use `*` for matching'
21
+ .help-block EXAMPLES: "hello,bye", "hello*,*bye*"
22
+ p= select_tag :locales, options_for_select(I18n.available_locales), multiple: true, class: 'fancy_select input-xxlarge', placeholder: 'Locales, all by default'
23
23
  button.btn Export CSV
24
24
 
25
25
  hr
26
26
 
27
27
  = form_tag import_admin_locators_path, method: :post, multipart: true do
28
28
  = file_field_tag :csv_file
29
- br
30
- input.input-medium.fancy_select> type='text' name='locales' placeholder='Locales, all by default' data-tags=I18n.available_locales.to_json
31
- br
32
- br
29
+ p= select_tag :locales, options_for_select(I18n.available_locales), multiple: true, class: 'fancy_select input-xxlarge', placeholder: 'Locales, all by default'
33
30
  button.btn Import CSV
34
31
 
@@ -9,16 +9,13 @@
9
9
  th.actions_panel
10
10
  - table_builder.fields.each do |field|
11
11
  th class=('hide_cell' if field.options[:hidden])
12
- - if field.options[:sortable].is_a?(FalseClass)
13
- = field.name.is_a?(Symbol) ? ha(field.name) : field.name
14
- - elsif field.options[:sortable].is_a?(TrueClass)
15
- = list_sort_link field.name
16
- - elsif field.options[:sortable].is_a?(Hash)
17
- = list_sort_link field.name, field.options[:sortable]
18
- - elsif resource_class.column_names.include?(field.name.to_s)
19
- = list_sort_link field.name
12
+ - field_title = field.options[:title] || (field.name.is_a?(Symbol) ? ha(field.name) : field.name)
13
+ - if field.options[:sortable].is_a?(Hash)
14
+ = list_sort_link field.name, field.options[:sortable].merge(title: field_title)
15
+ - elsif field.options[:sortable].is_a?(TrueClass) || (!field.options[:sortable].is_a?(FalseClass) && resource_class.column_names.include?(field.name.to_s))
16
+ = list_sort_link field.name, title: field_title
20
17
  - else
21
- = field.name.is_a?(Symbol) ? ha(field.name) : field.name
18
+ = field_title
22
19
  tbody
23
20
  - is_edit_link = manager.actions.include?(:edit)
24
21
  - collection.each do |item|
@@ -27,7 +24,7 @@
27
24
  td= id_link(item, edit: is_edit_link)
28
25
  = item_index_actions_panel(item)
29
26
  - table_builder.fields.each do |field|
30
- td class=(field.options[:css_class] if field.options[:css_class])
27
+ td class=(field.options[:cell_class] if field.options[:cell_class])
31
28
  - field_content = table_item_field(item, field)
32
29
  - if field.options[:copy_button]
33
30
  - field_id = dom_id(item, field.name)
@@ -21,7 +21,7 @@
21
21
  - param_name = opts[:as] || name
22
22
  - active = params[param_name]
23
23
  a.btn href=url_for(param_name => (active ? nil : 1)) class=('active' if active)
24
- = t "admin.scopes.#{name}", default: name.to_s.titleize
24
+ = opts[:title] || t("admin.scopes.#{name}", default: name.to_s.titleize)
25
25
  - if opts[:badge]
26
26
  - scope = opts[:block] ? opts[:block].call(controller, resource_class) : resource_class.send(name)
27
27
  - scope_count = scope.send(*[opts[:badge][:value_type] || :count, opts[:badge][:column]].compact)
@@ -4,7 +4,7 @@ nav.navbar-inner
4
4
  span.icon-bar
5
5
  span.icon-bar
6
6
  span.icon-bar
7
- a.brand href=(AbAdmin.root_path || root_path) target='_blank' = AbAdmin.site_name
7
+ a.brand href=(AbAdmin.root_path || root_path) target='_blank' = admin_site_name
8
8
  .nav-collapse.collapse
9
9
  = AdminMenu.render(self)
10
10
 
@@ -1,10 +1,10 @@
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
6
-
7
1
  = cache [I18n.locale, 'admin', 'footer'] do
2
+ - if AbAdmin.footer
3
+ footer
4
+ ' Powered by
5
+ a href='https://github.com/leschenko/ab_admin' target='_blank' = "AbAdmin #{AbAdmin::VERSION}"
6
+ .muted.footer-notes= AbAdmin.footer_notes
7
+
8
8
  = render 'admin/fileupload/asset_templates'
9
9
  = render 'admin/shared/columns_hider'
10
10
 
@@ -3,10 +3,9 @@ html id="controller_#{controller_name}"
3
3
  head
4
4
  meta charset='utf-8'
5
5
  meta name='viewport' content='width=device-width, initial-scale=1.0'
6
- title= @page_title || AbAdmin.site_name
6
+ meta name="robots" content="noindex,nofollow"
7
+ title= @page_title || admin_site_name
7
8
  = stylesheet_link_tag 'ab_admin/devise', media: 'all'
8
- script src='//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js'
9
- = javascript_include_tag 'bootstrap'
10
9
  = csrf_meta_tags
11
10
  body.container
12
11
  = render('admin/shared/flash', flash: flash) if flash
@@ -13,7 +13,7 @@ en:
13
13
  zero: History
14
14
  attributes:
15
15
  user:
16
- password_confirmation: ''
16
+ password_confirmation: 'Password confirmation'
17
17
  admin:
18
18
  actions:
19
19
  activate:
@@ -116,11 +116,11 @@ en:
116
116
  save_and_edit_prev: Save and prev.
117
117
  details: More
118
118
  base: Base
119
- keywords: ''
119
+ keywords: 'keywords'
120
120
  gender:
121
121
  female: Female
122
122
  male: Male
123
- undefined: ''
123
+ undefined: 'undefined'
124
124
  geo_autocomplete: Enter the address
125
125
  group:
126
126
  kind:
@@ -242,8 +242,8 @@ en:
242
242
  updated_at: Updated at
243
243
  user: User
244
244
  user_id: User
245
- updater: ''
246
- updater_id: ''
245
+ updater: 'Updater'
246
+ updater_id: 'Updater'
247
247
  remember_me: Remember
248
248
  password: Password
249
249
  flash:
@@ -55,8 +55,8 @@ module AbAdmin
55
55
  instance.show = ::AbAdmin::Config::Show.new(options, &block)
56
56
  end
57
57
 
58
- def preview_path(value=nil, &block)
59
- instance.preview_path = block_given? ? block : value
58
+ def preview_path(value=nil, options={}, &block)
59
+ instance.preview_path = {value: block_given? ? block : value, options: options}
60
60
  end
61
61
 
62
62
  def permitted_params(*values, &block)
@@ -35,11 +35,9 @@ module AbAdmin
35
35
  end
36
36
 
37
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
38
+ return if version_name == :default
39
+ return secure_token unless version_name
40
+ version_name.to_s.start_with?('retina_') ? "#{version_name.to_s.sub(/^retina_/, '')}@2x" : version_name.to_s
43
41
  end
44
42
 
45
43
  def full_filename(for_file=filename)
@@ -48,9 +46,10 @@ module AbAdmin
48
46
 
49
47
  def human_full_filename(for_file=filename)
50
48
  ext = File.extname(for_file)
49
+ system_part = base_filename_part
51
50
  human_filename_part = for_file.chomp(ext)
52
- tech_filename_part = "#{base_filename_part}#{ext}"
53
- human_filename_part == secure_token ? tech_filename_part : "#{human_filename_part}_#{tech_filename_part}"
51
+ return "#{system_part || version_name}#{ext}" if human_filename_part == secure_token
52
+ system_part ? "#{human_filename_part}_#{system_part}#{ext}" : "#{human_filename_part}#{ext}"
54
53
  end
55
54
 
56
55
  def full_original_filename
@@ -4,7 +4,7 @@ module AbAdmin
4
4
  extend ActiveSupport::Concern
5
5
 
6
6
  included do
7
- scope(:admin, -> { all }) unless respond_to?(:admin)
7
+ scope(:admin, proc { all }) unless respond_to?(:admin)
8
8
  scope(:base, -> { all }) unless respond_to?(:base)
9
9
  scope :by_ids, lambda { |ids| where("#{quoted_table_name}.id IN (?)", AbAdmin.val_to_array(ids).push(0)) } unless respond_to?(:by_ids)
10
10
 
@@ -22,6 +22,10 @@ module AbAdmin
22
22
  def default_header
23
23
  header || build_header
24
24
  end
25
+
26
+ def default_persistent_header
27
+ header || create_header
28
+ end
25
29
  end
26
30
  end
27
31
  end
@@ -18,10 +18,9 @@ module AbAdmin
18
18
 
19
19
  def self.default_for_model(model, options={})
20
20
  new.tap do |builder|
21
- builder.field(:id) unless options[:skip].try(:include?, :id)
22
21
  model.column_names.each do |column|
23
22
  column_name = column.to_sym
24
- next if options[:skip].try(:include?, column_name)
23
+ next if column_name == :id || options[:skip].try(:include?, column_name)
25
24
  builder.field(column_name)
26
25
  end
27
26
  end
@@ -52,7 +51,7 @@ module AbAdmin
52
51
  self.partial_name = 'form'
53
52
 
54
53
  def group(name=nil, options={}, &block)
55
- options[:title] = name || :base
54
+ options[:title] = name
56
55
  @fields << FieldGroup.new(options, &block)
57
56
  end
58
57
 
@@ -9,7 +9,7 @@ module AbAdmin
9
9
  return text if from == to
10
10
  base = 'https://www.googleapis.com/language/translate/v2'
11
11
  params = {
12
- key: configatron.else.retrieve(:google_api_key, ENV['GOOGLE_API_KEY']),
12
+ key: ENV['GOOGLE_API_KEY'] || Settings.data.else.try!(:google_api_key),
13
13
  format: 'html',
14
14
  source: from,
15
15
  target: to,
@@ -17,7 +17,7 @@ module AbAdmin
17
17
  after_create :increment_counter_cache
18
18
  before_destroy :decrement_counter_cache
19
19
 
20
- scope :admin, lambda { includes(:user, :attachment_files) }
20
+ scope :admin, proc { includes(:user, :attachment_files) }
21
21
 
22
22
  fileuploads :attachment_files
23
23
  end
@@ -58,13 +58,14 @@ module AbAdmin
58
58
 
59
59
  def as_json(options = nil)
60
60
  options = {
61
- only: [:id, :guid, :assetable_id, :assetable_type, :user_id, :data_file_size, :data_content_type, :is_main,
62
- :original_name, :cached_alt, :cached_title],
63
61
  root: 'asset',
62
+ only: [:id, :guid, :assetable_id, :assetable_type, :user_id, :data_file_size, :data_content_type, :is_main, :original_name],
64
63
  methods: [:filename, :url, :thumb_url, :width, :height]
65
64
  }.merge(options || {})
66
65
 
67
- super
66
+ res = super
67
+ I18n.with_locale(assetable.try(:locale)) { (res[options[:root]] || res).update('name' => name, 'alt' => alt) }
68
+ res
68
69
  end
69
70
 
70
71
  def has_dimensions?
@@ -3,6 +3,7 @@ require 'csv'
3
3
  module AbAdmin
4
4
  module Models
5
5
  module Locator
6
+ YAML_LINE_WIDTH = 200
6
7
  extend ActiveSupport::Concern
7
8
 
8
9
  included do
@@ -19,7 +20,7 @@ module AbAdmin
19
20
 
20
21
  def save(path, data)
21
22
  data.deep_transform_values! { |v| AbAdmin.normalize_html(v) }
22
- File.write path, data.deep_stringify_keys.to_yaml.sub(/\A---\s+/, '').gsub(/:\s+$/, ':').gsub(/^(\s+)(yes|no):/, '\1"\2":')
23
+ File.write path, data.deep_stringify_keys.to_yaml(line_width: YAML_LINE_WIDTH).sub(/\A---\s+/, '').gsub(/:\s+$/, ':').gsub(/^(\s+)(yes|no):/, '\1"\2":')
23
24
  end
24
25
 
25
26
  def prepare_data(path)
@@ -29,14 +30,16 @@ module AbAdmin
29
30
  filename: File.basename(path), path: path, dir: File.dirname(path)})
30
31
  end
31
32
 
32
- def export_csv(*keys, locales: nil)
33
+ def export_csv(*keys, locales: nil, files: nil)
33
34
  return if keys.blank?
34
- locales ||= I18n.available_locales
35
+ sources = files.present? ? translations_for_files(files) : translations
36
+ locales = locales.present? ? (I18n.available_locales & locales.map(&:to_sym)) : (sources.keys || I18n.available_locales)
35
37
  I18n.backend.available_locales # Force load translations
36
38
  filter_keys = keys.map {|k| k.include?('*') ? Regexp.new("\\A#{k.gsub('.', '\.').gsub('*', '.*')}\\z") : k}
37
39
  data = filter_keys.each_with_object(Hash.new { |h, k| h[k] = [] }) do |key, res|
38
40
  locales.each_with_index do |l, i|
39
- translations[l].find_all{|k, _| key.is_a?(Regexp) ? k =~ key : k == key }.each{|k, v| res[k][i] = v}
41
+ next unless sources[l]
42
+ sources[l].find_all{|k, _| key.is_a?(Regexp) ? k =~ key : k == key }.each{|k, v| res[k][i] = v}
40
43
  end
41
44
  end
42
45
  for_csv = [['DO NOT EDIT THIS COLUMN!', *locales]] + data.map{|k, v| [k, *v] }
@@ -45,7 +48,7 @@ module AbAdmin
45
48
 
46
49
  def import_csv(csv, locales: nil)
47
50
  return if csv.blank?
48
- locales ||= I18n.available_locales
51
+ locales = locales.present? ? (I18n.available_locales & locales.map(&:to_sym)) : I18n.available_locales
49
52
  csv_data = CSV.parse(csv)
50
53
  csv_data.shift.each_with_index do |l, i|
51
54
  next if i.zero? || !locales.include?(l.to_sym)
@@ -64,6 +67,16 @@ module AbAdmin
64
67
  def translations
65
68
  @translations ||= I18n.backend.send(:translations).slice(*I18n.available_locales).transform_values{|v| v.flatten_hash.transform_keys{|k| k.join('.') } }
66
69
  end
70
+
71
+ def translations_for_files(files)
72
+ data = {}
73
+ files.each do |file|
74
+ path = Rails.root.join('config', 'locales', file)
75
+ puts path
76
+ data.deep_merge!(YAML.load_file(path))
77
+ end
78
+ data.symbolize_keys.slice(*I18n.available_locales).transform_values{|v| v.flatten_hash.transform_keys{|k| k.join('.') } }
79
+ end
67
80
  end
68
81
 
69
82
  def initialize
@@ -6,7 +6,7 @@ module AbAdmin
6
6
  included do
7
7
  extend ActiveModel::Naming
8
8
  extend ActiveRecord::Translation
9
- class_attribute :base_class, :base_dir, :base_paths, :editable_paths
9
+ class_attribute :data_cache, :base_class, :base_dir, :base_paths, :editable_paths
10
10
  self.base_class = self
11
11
  self.base_dir = Rails.root.join('config', 'settings')
12
12
  self.base_paths = [
@@ -17,63 +17,58 @@ module AbAdmin
17
17
  File.join(base_dir, "#{Rails.env}.local.yml"),
18
18
  File.join(base_dir, 'settings.local.yml')
19
19
  ]
20
+
21
+ class << self
22
+ delegate :get, :dig, to: :data, allow_nil: true
23
+ end
20
24
  end
21
25
 
22
26
  module ClassMethods
23
27
  def load_config
24
- configatron.configure_from_hash instance.all
25
- configatron
28
+ ActiveSupport::Deprecation.warn('`Settings.load_config` is deprecated, use `Settings.data` instead')
29
+ data
26
30
  end
27
- end
28
31
 
29
- def initialize
30
- @data = {}
31
- @paths = find_paths
32
- end
32
+ def data
33
+ self.data_cache ||= read_data
34
+ end
33
35
 
34
- def editable
35
- return {} unless editable_path
36
- YAML.load_file(editable_path) rescue {}
37
- end
36
+ def reload_data
37
+ self.data_cache = read_data
38
+ end
38
39
 
39
- def save(raw_config)
40
- config = {}
41
- raw_config.each do |root_key, root_value|
42
- if root_value.is_a?(Hash)
43
- config[root_key] ||= {}
44
- root_value.each do |key, value|
45
- config[root_key][key] = typecast_value(value)
46
- end
47
- else
48
- config[root_key] = typecast_value(root_value)
49
- end
40
+ def read_data
41
+ paths = base_paths.dup.push(editable_path).compact.find_all { |path| File.exists?(path) }
42
+ hash = paths.map{|path| YAML.safe_load(File.read(path)) }.inject(&:deep_merge).deep_symbolize_keys
43
+ SettingsStruct.new(hash)
50
44
  end
51
- return unless editable_path
52
- File.open(editable_path, 'w') { |file| file.write config.to_yaml } and self.class.load_config
53
- end
54
45
 
55
- def all
56
- @paths.each do |path|
57
- @data.deep_merge!(YAML.load_file(path))
46
+ def editable_data
47
+ YAML.safe_load(File.read(editable_path))
58
48
  end
59
- @data
60
- end
61
49
 
62
- private
50
+ def update(raw_config)
51
+ config = YAML.safe_load(YAML.dump(raw_config.to_hash.deep_stringify_keys.deep_transform_values!{|v| YAML.safe_load(v) }))
52
+ File.write(editable_path, config.to_yaml)
53
+ end
63
54
 
64
- def editable_path
65
- @editable_path ||= editable_paths.detect { |path| File.exists?(path) }
55
+ def editable_path
56
+ editable_paths.detect { |path| File.exists?(path) }
57
+ end
66
58
  end
67
59
 
68
- def find_paths
69
- base_paths.dup.unshift(editable_path).compact.find_all { |path| File.exists?(path) }
70
- end
60
+ class SettingsStruct < OpenStruct
61
+ def initialize(hash=nil)
62
+ @table = {}
63
+ return unless hash
64
+ hash.symbolize_keys.each do |k, v|
65
+ k = k.to_sym
66
+ @table[k] = v.is_a?(Hash) ? SettingsStruct.new(v.symbolize_keys) : v
67
+ end
68
+ end
71
69
 
72
- def typecast_value(value)
73
- if %w(true false).include?(value) || value.to_s.is_number?
74
- YAML::load(value)
75
- else
76
- value
70
+ def get(key)
71
+ dig *key.split('.').map(&:to_sym)
77
72
  end
78
73
  end
79
74
  end
@@ -8,7 +8,7 @@ module AbAdmin
8
8
 
9
9
  scope :managers, -> { where(user_role_id: [::UserRoleType.admin.id, ::UserRoleType.moderator.id]) }
10
10
  scope :active, -> { where(locked_at: nil) }
11
- scope :admin, -> { includes(:avatar) }
11
+ scope :admin, proc { includes(:avatar) }
12
12
 
13
13
  after_initialize :init
14
14
  before_validation :generate_login
@@ -28,7 +28,7 @@ module AbAdmin
28
28
  end
29
29
 
30
30
  def suspend!
31
- update_attribute(:locked_at, Time.now.utc)
31
+ lock_access!
32
32
  end
33
33
 
34
34
  def activate!
@@ -65,8 +65,7 @@ module AbAdmin
65
65
  # html like: '<!-- html comment --><script>script content</script><div>div content</div><p>p content</p>'
66
66
  # normalized to: "<p>div content</p><p>p content</p>"
67
67
  def normalize_html(raw_html, options = {}, &block)
68
- @@sanitizer ||= Sanitizer.new(options)
69
- @@sanitizer.normalize_html(raw_html, options[:sanitize] || {}, &block)
68
+ Sanitizer.new(options).normalize_html(raw_html, options[:sanitize] || {}, &block)
70
69
  end
71
70
 
72
71
  def url_helpers
@@ -87,13 +87,15 @@ module AbAdmin
87
87
  def call_method_or_proc_on(obj, symbol_or_proc, options = {})
88
88
  exec = options[:exec].nil? ? true : options[:exec]
89
89
  case symbol_or_proc
90
- when Symbol, String
91
- obj.send(symbol_or_proc.to_sym, *options[:attrs])
90
+ when String
91
+ ActiveSupport::Deprecation.warn('`call_method_or_proc_on` don\'t accept method name as String, use Symbol instead') if symbol_or_proc =~ /\A\w+\z/
92
+ symbol_or_proc
93
+ when Symbol
94
+ obj.public_send(symbol_or_proc.to_sym, *options[:attrs])
92
95
  when Proc
93
96
  exec ? obj.instance_exec(&symbol_or_proc) : symbol_or_proc.call(obj)
94
97
  end
95
98
  end
96
-
97
99
  end
98
100
  end
99
101
  end
@@ -1,3 +1,3 @@
1
1
  module AbAdmin
2
- VERSION = '0.8.2'
2
+ VERSION = '0.8.3'
3
3
  end
@@ -21,52 +21,64 @@ module AbAdmin
21
21
  end
22
22
  end
23
23
 
24
- def editable_bool(item, attr)
24
+ def editable_bool(item, attr, label: nil)
25
25
  url = "/admin/#{item.class.model_name.plural}/#{item.id}.json"
26
- content_tag :div, class: 'auto-submit-checkbox-wrap' do
27
- check_box_tag("#{item.class.model_name.singular}[#{attr}]", '1', item.send(attr), class: 'js-auto-submit-checkbox', data: {url: url})
28
- end
26
+ html = check_box_tag("#{item.class.model_name.singular}[#{attr}]", '1', item.send(attr), class: 'js-auto-submit-checkbox', data: {url: url})
27
+ html = content_tag(:label, "#{label}&nbsp;#{html}".html_safe) if label
28
+ content_tag :div, html, class: 'auto-submit-checkbox-wrap white-space-nowrap'
29
29
  end
30
30
 
31
- def admin_editable(item, attr, options=nil)
32
- options = {} unless options.is_a?(Hash)
33
- title = options[:title] || item[attr]
31
+ def admin_editable(item, attr, opts=nil)
32
+ opts = {} unless opts.is_a?(Hash)
33
+ if opts[:title]
34
+ title = opts[:title]
35
+ else
36
+ assoc_name = attr.to_s.remove('_id')
37
+ title = item.class.reflect_on_association(assoc_name) ? AbAdmin.display_name(item.send(assoc_name)) : item[attr]
38
+ end
34
39
  html_title = admin_pretty_data(title).to_s.html_safe
35
40
  return html_title unless can?(:update, item)
36
- options[:source] = options[:collection].is_a?(Hash) ? options[:collection] : options[:collection].map{|r| [r.id, AbAdmin.display_name(r)] }.to_h if options[:collection]
37
41
 
38
- unless options[:type]
39
- if options[:source]
40
- options[:type] = 'select'
42
+ if opts[:collection]
43
+ if opts[:collection].is_a?(Hash)
44
+ opts[:source] = opts[:collection]
45
+ elsif opts[:collection].is_a?(Array)
46
+ opts[:source] = opts[:collection].first.respond_to?(:id) ? opts[:collection].map {|r| [r.id, AbAdmin.display_name(r)]}.to_h : opts[:collection].map {|v| [v, v]}.to_h
47
+ end
48
+ end
49
+
50
+ unless opts[:type]
51
+ if opts[:source]
52
+ opts[:type] = 'select'
41
53
  else
42
54
  case attr.to_s
43
55
  when /_at$/
44
- options[:type] ||= 'date'
45
- options[:title] ||= html_title
56
+ opts[:type] ||= 'date'
57
+ opts[:title] ||= html_title
46
58
  when /^is_/
47
- options[:type] ||= 'select'
48
- options[:source] ||= {1 => 'yes', 0 => 'no'}
49
- options[:value] ||= item[attr] ? 1 : 0
50
- options[:title] ||= item[attr] ? 'yes' : 'no'
59
+ opts[:type] ||= 'select'
60
+ opts[:source] ||= {1 => 'yes', 0 => 'no'}
61
+ opts[:value] ||= item[attr] ? 1 : 0
62
+ opts[:title] ||= item[attr] ? 'yes' : 'no'
51
63
  when /description|body|content/
52
- options[:type] ||= 'textarea'
64
+ opts[:type] ||= 'textarea'
53
65
  else
54
- options[:type] ||= 'text'
66
+ opts[:type] ||= 'text'
55
67
  end
56
68
  end
57
69
  end
58
70
 
59
71
  data = {
60
- type: options[:type],
61
- source: options[:source].try(:to_json),
62
- model: options[:model] || item.class.model_name.singular,
63
- accept: options[:accept],
64
- url: options[:url] || "/admin/#{item.class.model_name.plural}/#{item.id}",
72
+ type: opts[:type],
73
+ source: opts[:source].try(:to_json),
74
+ model: opts[:model] || item.class.model_name.singular,
75
+ accept: opts[:accept],
76
+ url: opts[:url] || "/admin/#{item.class.model_name.plural}/#{item.id}",
65
77
  name: attr,
66
- value: options[:value] || item[attr],
67
- title: options[:title] || item[attr]
78
+ value: opts[:value] || item[attr],
79
+ title: opts[:title] || item[attr]
68
80
  }
69
- link_to html_title, '#', class: "editable #{options[:class]}", data: data.update(options[:data] || {})
81
+ link_to html_title, '#', class: "editable #{opts[:class]}", data: data.update(opts[:data] || {})
70
82
  end
71
83
 
72
84
  def options_for_ckeditor(options = {})
@@ -162,7 +174,7 @@ module AbAdmin
162
174
  # input_set 'title', legend_class: 'do_sort', label_class: 'label-info' do
163
175
  def input_set(title, options={}, &block)
164
176
  options.reverse_merge!(class: "inputs well well-small clearfix #{options.delete(:legend_class) || 'do_sort'}", id: options.delete(:legend_id))
165
- html = content_tag(:label, title, class: "input_set label #{options.delete(:label_class)}")
177
+ html = title ? content_tag(:label, title, class: "input_set label #{options.delete(:label_class)}") : ''.html_safe
166
178
  html.concat(capture(&block)) if block_given?
167
179
  content_tag(:div, html, options)
168
180
  end
@@ -171,16 +183,22 @@ module AbAdmin
171
183
  resource_class.han(attr)
172
184
  end
173
185
 
186
+ def admin_site_name
187
+ AbAdmin.site_name.is_a?(String) ? AbAdmin.site_name : AbAdmin.site_name.call
188
+ end
189
+
174
190
  def call_method_or_proc_on(obj, symbol_or_proc, options = {})
175
191
  exec = options[:exec].nil? ? true : options[:exec]
176
192
  case symbol_or_proc
177
- when Symbol, String
193
+ when String
194
+ ActiveSupport::Deprecation.warn('`call_method_or_proc_on` don\'t accept method name as String, use Symbol instead') if symbol_or_proc =~ /\A\w+\z/
195
+ symbol_or_proc
196
+ when Symbol
178
197
  obj.send(symbol_or_proc.to_sym)
179
198
  when Proc
180
199
  exec ? instance_exec(obj, &symbol_or_proc) : symbol_or_proc.call(obj)
181
200
  end
182
201
  end
183
-
184
202
  end
185
203
  end
186
204
  end
@@ -20,20 +20,19 @@ module AbAdmin
20
20
  if adapter && adapter.klass == resource_class
21
21
  sort_link(adapter, attribute, options)
22
22
  else
23
- attribute.is_a?(Symbol) ? ha(attribute) : attribute
23
+ options[:title] || (attribute.is_a?(Symbol) ? ha(attribute) : attribute)
24
24
  end
25
25
  end
26
26
 
27
- def sort_link(search, attribute, *args)
28
- name = attribute.is_a?(Symbol) ? ha(attribute) : attribute
29
- return name unless search
30
-
31
- options = args.first.is_a?(Hash) ? args.shift.dup : {}
27
+ def sort_link(adapter, attribute, options={})
28
+ name = options[:title] || (attribute.is_a?(Symbol) ? ha(attribute) : attribute)
29
+ return name unless adapter
32
30
  search_params = (params[:q] || {}).to_h.with_indifferent_access
33
31
  attr_name = (options.delete(:column) || attribute).to_s
34
32
  default_order = options.delete :default_order
35
33
 
36
- if existing_sort = search.sorts.detect { |s| s.name == attr_name }
34
+ existing_sort = adapter.sorts.detect { |s| s.name == attr_name }
35
+ if existing_sort
37
36
  prev_attr, prev_dir = existing_sort.name, existing_sort.dir
38
37
  current_dir = prev_attr == attr_name ? prev_dir : nil
39
38
  else
@@ -21,8 +21,8 @@ module AbAdmin
21
21
  @options[:container_class] = container_class
22
22
  end
23
23
 
24
- def input(wrapper_options=nil)
25
- title = options[:title] || object.class.han(attribute_name)
24
+ def input(*)
25
+ title = options[:title] || object.class.han(attribute_name) if options[:title] || !options.key?(:title)
26
26
  template.capture do
27
27
  if @options[:unwrapped]
28
28
  render_input
@@ -1,7 +1,5 @@
1
1
  require 'ab_admin/hooks'
2
2
 
3
- Settings.load_config
4
-
5
3
  I18n.available_locales = Globalize.available_locales = [:ru, :en]
6
4
 
7
5
  AbAdmin.setup do |config|
@@ -1,12 +1,8 @@
1
- require 'configatron'
2
-
3
1
  class Settings
4
2
  include Singleton
5
3
  include AbAdmin::Models::Settings
6
4
  include ::AbAdmin::Concerns::Reloadable
7
5
 
8
- has_reload_check('settings_reload_key', Rails.logger) { Settings.load_config }
9
-
10
- attr_accessor :paths, :data
6
+ has_reload_check('settings_reload_key', Rails.logger) { Settings.reload_data }
11
7
 
12
8
  end
@@ -18,11 +18,9 @@ class AbAdmin<%= model.name %> < AbAdmin::AbstractResource
18
18
  <% end -%>
19
19
 
20
20
  form do
21
- group :base do
22
21
  <% index_attrs.without('id', 'created_at', 'updated_at', 'lat', 'lon', 'zoom', 'lft', 'rgt', 'depth').without(*translated_columns).each do |attr| -%>
23
- field :<%= attr %>
22
+ field :<%= attr %>
24
23
  <% end -%>
25
- end
26
24
  <% unless translated_columns.empty? -%>
27
25
  locale_tabs do
28
26
  <% translated_columns.each do |attr| -%>
@@ -19,8 +19,6 @@ gem 'globalize', github: 'globalize/globalize'
19
19
 
20
20
  gem 'carrierwave'
21
21
  gem 'mini_magick'
22
- # 3.0 is broken - creates new `configatron` instance in every namespace
23
- gem 'configatron', '~> 2.13'
24
22
  gem 'simple_form'
25
23
  gem 'coffee-rails'
26
24
  gem 'sass-rails'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ab_admin
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.8.2
4
+ version: 0.8.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alex Leschenko
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-02-04 00:00:00.000000000 Z
11
+ date: 2019-06-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -408,27 +408,6 @@ files:
408
408
  - app/assets/images/admin/flags/ja.png
409
409
  - app/assets/images/admin/flags/pl.png
410
410
  - app/assets/images/admin/flags/ru.png
411
- - app/assets/images/admin/flags/toremove/b_de.png
412
- - app/assets/images/admin/flags/toremove/b_en.png
413
- - app/assets/images/admin/flags/toremove/b_es.png
414
- - app/assets/images/admin/flags/toremove/b_fr.png
415
- - app/assets/images/admin/flags/toremove/b_it.png
416
- - app/assets/images/admin/flags/toremove/b_ru.png
417
- - app/assets/images/admin/flags/toremove/b_uk.png
418
- - app/assets/images/admin/flags/toremove/flag_de.gif
419
- - app/assets/images/admin/flags/toremove/flag_de_nonact.gif
420
- - app/assets/images/admin/flags/toremove/flag_en.gif
421
- - app/assets/images/admin/flags/toremove/flag_en_nonact.gif
422
- - app/assets/images/admin/flags/toremove/flag_es.gif
423
- - app/assets/images/admin/flags/toremove/flag_es_nonact.gif
424
- - app/assets/images/admin/flags/toremove/flag_fr.gif
425
- - app/assets/images/admin/flags/toremove/flag_fr_nonact.gif
426
- - app/assets/images/admin/flags/toremove/flag_it.gif
427
- - app/assets/images/admin/flags/toremove/flag_it_nonact.gif
428
- - app/assets/images/admin/flags/toremove/flag_ru.gif
429
- - app/assets/images/admin/flags/toremove/flag_ru_nonact.gif
430
- - app/assets/images/admin/flags/toremove/flag_uk.gif
431
- - app/assets/images/admin/flags/toremove/flag_uk_nonact.gif
432
411
  - app/assets/images/admin/flags/uk.png
433
412
  - app/assets/images/admin/main_image.png
434
413
  - app/assets/images/admin/preloader.gif
@@ -442,14 +421,12 @@ files:
442
421
  - app/assets/javascripts/ab_admin/components/grid_input.js.coffee
443
422
  - app/assets/javascripts/ab_admin/components/hotkeys.js.coffee
444
423
  - app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee
445
- - app/assets/javascripts/ab_admin/components/init_nested_filelds.js.coffee
446
424
  - app/assets/javascripts/ab_admin/components/locator.js.coffee
447
425
  - app/assets/javascripts/ab_admin/components/select2_bridge.js.coffee
448
426
  - app/assets/javascripts/ab_admin/components/sortable_tree.js.coffee
449
427
  - app/assets/javascripts/ab_admin/core/batch_actions.js.coffee
450
428
  - app/assets/javascripts/ab_admin/core/columns_hider.js.coffee
451
429
  - app/assets/javascripts/ab_admin/core/confirmation.js.coffee
452
- - app/assets/javascripts/ab_admin/core/deprecated_utils.js.coffee
453
430
  - app/assets/javascripts/ab_admin/core/init.js.coffee
454
431
  - app/assets/javascripts/ab_admin/core/pagination.js.coffee
455
432
  - app/assets/javascripts/ab_admin/core/pjax.js.coffee
@@ -500,6 +477,7 @@ files:
500
477
  - app/views/admin/admin_comments/destroy.js.erb
501
478
  - app/views/admin/admin_comments/index.js.erb
502
479
  - app/views/admin/assets/batch_edit.html.slim
480
+ - app/views/admin/assets/batch_update.js.erb
503
481
  - app/views/admin/base/_form.html.slim
504
482
  - app/views/admin/base/_modal_form_layout.html.slim
505
483
  - app/views/admin/base/_search_form.html.slim
@@ -728,8 +706,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
728
706
  - !ruby/object:Gem::Version
729
707
  version: '0'
730
708
  requirements: []
731
- rubyforge_project:
732
- rubygems_version: 2.6.12
709
+ rubygems_version: 3.0.3
733
710
  signing_key:
734
711
  specification_version: 4
735
712
  summary: Simple and real-life tested Rails::Engine admin interface based on slim,
@@ -1,7 +0,0 @@
1
- window.initNestedFields = (opts={}) ->
2
- $(document).on 'nested:fieldAdded', 'form.simple_form', (e) =>
3
- window.locale_tabs?.initHandlers() unless opts.skip_tabs
4
- window.initFancySelect() unless opts.skip_fancy
5
- window.initPickers() unless opts.skip_pickers
6
- window.initEditor() unless opts.skip_editor
7
- opts.callback.call(e) if opts.callback
@@ -1,44 +0,0 @@
1
- Array::last = ->
2
- if @.length > 0
3
- @[@.length - 1]
4
-
5
- Array::first = ->
6
- @[0]
7
-
8
- Array::removeByIndex = (arrayIndex)->
9
- @.splice(arrayIndex, 1)
10
-
11
- Array::valDetect = (v, prop = 'id') ->
12
- res = null
13
- for el in @
14
- if el[prop] is v
15
- res = el
16
- res
17
-
18
- Array::includes = (obj) ->
19
- for el, i in @
20
- if el == obj
21
- return i
22
- return false
23
-
24
- Array::remove = ->
25
- what = undefined
26
- a = arguments
27
- L = a.length
28
- ax = undefined
29
- while L and @length
30
- what = a[--L]
31
- until (ax = @indexOf(what)) is -1
32
- @splice ax, 1
33
- break;
34
- this
35
-
36
- String::parseQuery = ->
37
- h = {}
38
- qs = $.trim(this).match(/([^?#]*)(#.*)?$/)[0]
39
- return {} unless qs
40
- pairs = qs.split("&")
41
- $.each pairs, (i, v) ->
42
- pair = v.split("=")
43
- h[pair[0]] = pair[1]
44
- h