ab_admin 0.8.2 → 0.8.3

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 (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