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.
- checksums.yaml +5 -5
- data/app/assets/javascripts/ab_admin/core/init.js.coffee +0 -1
- data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +8 -0
- data/app/assets/javascripts/ab_admin/main.js +0 -1
- data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.scss +1 -1
- data/app/assets/stylesheets/ab_admin/components/_form.scss +23 -2
- data/app/assets/stylesheets/ab_admin/components/_table_view.scss +1 -0
- data/app/controllers/admin/assets_controller.rb +1 -1
- data/app/controllers/admin/locators_controller.rb +2 -4
- data/app/controllers/admin/manager_controller.rb +2 -1
- data/app/controllers/admin/settings_controller.rb +2 -2
- data/app/views/admin/assets/batch_update.js.erb +4 -0
- data/app/views/admin/base/new.js.erb +1 -1
- data/app/views/admin/fileupload/_asset_templates.html.slim +1 -1
- data/app/views/admin/fileupload/_image.html.slim +2 -1
- data/app/views/admin/locators/show.html.slim +6 -9
- data/app/views/admin/manager/_table.html.slim +7 -10
- data/app/views/admin/shared/_content_actions.html.slim +1 -1
- data/app/views/admin/shared/_main_menu.html.slim +1 -1
- data/app/views/layouts/admin/_footer.html.slim +6 -6
- data/app/views/layouts/admin/devise.html.slim +2 -3
- data/config/locales/en.yml +5 -5
- data/lib/ab_admin/abstract_resource.rb +2 -2
- data/lib/ab_admin/carrierwave/base_uploader.rb +6 -7
- data/lib/ab_admin/concerns/admin_addition.rb +1 -1
- data/lib/ab_admin/concerns/headerable.rb +4 -0
- data/lib/ab_admin/config/base.rb +2 -3
- data/lib/ab_admin/i18n_tools/google_translate.rb +1 -1
- data/lib/ab_admin/models/admin_comment.rb +1 -1
- data/lib/ab_admin/models/asset.rb +4 -3
- data/lib/ab_admin/models/locator.rb +18 -5
- data/lib/ab_admin/models/settings.rb +37 -42
- data/lib/ab_admin/models/user.rb +2 -2
- data/lib/ab_admin/utils.rb +1 -2
- data/lib/ab_admin/utils/eval_helpers.rb +5 -3
- data/lib/ab_admin/version.rb +1 -1
- data/lib/ab_admin/views/admin_helpers.rb +48 -30
- data/lib/ab_admin/views/admin_navigation_helpers.rb +6 -7
- data/lib/ab_admin/views/inputs/uploader_input.rb +2 -2
- data/lib/generators/ab_admin/install/templates/config/ab_admin.rb.erb +0 -2
- data/lib/generators/ab_admin/install/templates/models/settings.rb +1 -5
- data/lib/generators/ab_admin/model/templates/resource.erb +1 -3
- data/lib/generators/template.rb +0 -2
- metadata +4 -27
- data/app/assets/images/admin/flags/toremove/b_de.png +0 -0
- data/app/assets/images/admin/flags/toremove/b_en.png +0 -0
- data/app/assets/images/admin/flags/toremove/b_es.png +0 -0
- data/app/assets/images/admin/flags/toremove/b_fr.png +0 -0
- data/app/assets/images/admin/flags/toremove/b_it.png +0 -0
- data/app/assets/images/admin/flags/toremove/b_ru.png +0 -0
- data/app/assets/images/admin/flags/toremove/b_uk.png +0 -0
- data/app/assets/images/admin/flags/toremove/flag_de.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_de_nonact.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_en.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_en_nonact.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_es.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_es_nonact.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_fr.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_fr_nonact.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_it.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_it_nonact.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_ru.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_ru_nonact.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_uk.gif +0 -0
- data/app/assets/images/admin/flags/toremove/flag_uk_nonact.gif +0 -0
- data/app/assets/javascripts/ab_admin/components/init_nested_filelds.js.coffee +0 -7
- data/app/assets/javascripts/ab_admin/core/deprecated_utils.js.coffee +0 -44
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
|
-
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 43ed57227cecaa2f87430c9c4d91b091a481d63a7c114f11815475d035d7c0fa
|
|
4
|
+
data.tar.gz: 3c468bae1894700743f5c78d9c833c57ece9638179174294e6a1ba90dd2cae54
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: f172fa06ba23701ba8d0849267642bbe51485951aed25d1f686a342b7b770d5983b0387886cc544c83269e653d026e31cae9fb3b2eacd40c2c5e402b2c032b3d
|
|
7
|
+
data.tar.gz: c90de19869723ace5d640bfc0b426cbfa7982f1555312dee5b990cf8a523bb09d4468c7fb1fd3297d5181987a892897638e8411690a06474539de0bb42e687fc
|
|
@@ -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
|
|
|
@@ -55,9 +55,9 @@ input[type="color"],
|
|
|
55
55
|
.form-actions {
|
|
56
56
|
position: fixed;
|
|
57
57
|
bottom: -20px;
|
|
58
|
-
left:
|
|
58
|
+
left: 0;
|
|
59
59
|
border-radius: 10px;
|
|
60
|
-
padding:
|
|
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;
|
|
@@ -6,15 +6,13 @@ class ::Admin::LocatorsController < ::Admin::BaseController
|
|
|
6
6
|
|
|
7
7
|
def export
|
|
8
8
|
authorize! :export, resource_class
|
|
9
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
-
@
|
|
24
|
+
@collection ||= Settings.editable_data
|
|
25
25
|
end
|
|
26
26
|
|
|
27
27
|
def collection_path
|
|
@@ -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='{{
|
|
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
|
-
|
|
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
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
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
|
-
|
|
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
|
-
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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
|
-
=
|
|
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[:
|
|
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
|
|
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' =
|
|
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
|
-
|
|
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
|
data/config/locales/en.yml
CHANGED
|
@@ -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
|
-
|
|
40
|
-
|
|
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
|
-
|
|
53
|
-
|
|
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,
|
|
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
|
|
data/lib/ab_admin/config/base.rb
CHANGED
|
@@ -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
|
|
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:
|
|
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,
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
25
|
-
|
|
28
|
+
ActiveSupport::Deprecation.warn('`Settings.load_config` is deprecated, use `Settings.data` instead')
|
|
29
|
+
data
|
|
26
30
|
end
|
|
27
|
-
end
|
|
28
31
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
end
|
|
32
|
+
def data
|
|
33
|
+
self.data_cache ||= read_data
|
|
34
|
+
end
|
|
33
35
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
end
|
|
36
|
+
def reload_data
|
|
37
|
+
self.data_cache = read_data
|
|
38
|
+
end
|
|
38
39
|
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
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
|
-
|
|
56
|
-
|
|
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
|
-
|
|
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
|
-
|
|
65
|
-
|
|
55
|
+
def editable_path
|
|
56
|
+
editable_paths.detect { |path| File.exists?(path) }
|
|
57
|
+
end
|
|
66
58
|
end
|
|
67
59
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
-
|
|
73
|
-
|
|
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
|
data/lib/ab_admin/models/user.rb
CHANGED
|
@@ -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,
|
|
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
|
-
|
|
31
|
+
lock_access!
|
|
32
32
|
end
|
|
33
33
|
|
|
34
34
|
def activate!
|
data/lib/ab_admin/utils.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
|
91
|
-
|
|
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
|
data/lib/ab_admin/version.rb
CHANGED
|
@@ -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
|
-
|
|
27
|
-
|
|
28
|
-
|
|
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} #{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,
|
|
32
|
-
|
|
33
|
-
|
|
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
|
-
|
|
39
|
-
if
|
|
40
|
-
|
|
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
|
-
|
|
45
|
-
|
|
56
|
+
opts[:type] ||= 'date'
|
|
57
|
+
opts[:title] ||= html_title
|
|
46
58
|
when /^is_/
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
-
|
|
64
|
+
opts[:type] ||= 'textarea'
|
|
53
65
|
else
|
|
54
|
-
|
|
66
|
+
opts[:type] ||= 'text'
|
|
55
67
|
end
|
|
56
68
|
end
|
|
57
69
|
end
|
|
58
70
|
|
|
59
71
|
data = {
|
|
60
|
-
type:
|
|
61
|
-
source:
|
|
62
|
-
model:
|
|
63
|
-
accept:
|
|
64
|
-
url:
|
|
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:
|
|
67
|
-
title:
|
|
78
|
+
value: opts[:value] || item[attr],
|
|
79
|
+
title: opts[:title] || item[attr]
|
|
68
80
|
}
|
|
69
|
-
link_to html_title, '#', class: "editable #{
|
|
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
|
|
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(
|
|
28
|
-
name = attribute.is_a?(Symbol) ? ha(attribute) : attribute
|
|
29
|
-
return name unless
|
|
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
|
-
|
|
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(
|
|
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,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.
|
|
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
|
-
|
|
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| -%>
|
data/lib/generators/template.rb
CHANGED
|
@@ -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.
|
|
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-
|
|
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
|
-
|
|
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,
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -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
|