ab_admin 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/images/admin/flags/de.png +0 -0
- data/app/assets/images/admin/flags/en.png +0 -0
- data/app/assets/images/admin/flags/es.png +0 -0
- data/app/assets/images/admin/flags/fr.png +0 -0
- data/app/assets/images/admin/flags/it.png +0 -0
- data/app/assets/images/admin/flags/ja.png +0 -0
- data/app/assets/images/admin/flags/pl.png +0 -0
- data/app/assets/images/admin/flags/ru.png +0 -0
- data/app/assets/images/admin/flags/{b_de.png → toremove/b_de.png} +0 -0
- data/app/assets/images/admin/flags/{b_en.png → toremove/b_en.png} +0 -0
- data/app/assets/images/admin/flags/{b_es.png → toremove/b_es.png} +0 -0
- data/app/assets/images/admin/flags/{b_fr.png → toremove/b_fr.png} +0 -0
- data/app/assets/images/admin/flags/{b_it.png → toremove/b_it.png} +0 -0
- data/app/assets/images/admin/flags/{b_ru.png → toremove/b_ru.png} +0 -0
- data/app/assets/images/admin/flags/{b_uk.png → toremove/b_uk.png} +0 -0
- data/app/assets/images/admin/flags/{flag_de.gif → toremove/flag_de.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_de_nonact.gif → toremove/flag_de_nonact.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_en.gif → toremove/flag_en.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_en_nonact.gif → toremove/flag_en_nonact.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_es.gif → toremove/flag_es.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_es_nonact.gif → toremove/flag_es_nonact.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_fr.gif → toremove/flag_fr.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_fr_nonact.gif → toremove/flag_fr_nonact.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_it.gif → toremove/flag_it.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_it_nonact.gif → toremove/flag_it_nonact.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_ru.gif → toremove/flag_ru.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_ru_nonact.gif → toremove/flag_ru_nonact.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_uk.gif → toremove/flag_uk.gif} +0 -0
- data/app/assets/images/admin/flags/{flag_uk_nonact.gif → toremove/flag_uk_nonact.gif} +0 -0
- data/app/assets/images/admin/flags/uk.png +0 -0
- data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +9 -1
- data/app/assets/javascripts/ab_admin/components/select2_bridge.js.coffee +1 -2
- data/app/assets/javascripts/ab_admin/core/init.js.coffee +5 -3
- data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +17 -0
- data/app/assets/javascripts/ab_admin/inputs/datetime_input.js.coffee +8 -3
- data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.scss +37 -8
- data/app/assets/stylesheets/ab_admin/components/_form.scss +31 -2
- data/app/assets/stylesheets/ab_admin/components/_locale_tabs.scss +13 -48
- data/app/assets/stylesheets/ab_admin/components/_navigation.scss +5 -0
- data/app/assets/stylesheets/ab_admin/main.scss +1 -1
- data/app/controllers/admin/base_controller.rb +14 -15
- data/app/controllers/admin/locators_controller.rb +18 -0
- data/app/controllers/admin/manager_controller.rb +6 -8
- data/app/controllers/admin/settings_controller.rb +1 -1
- data/app/controllers/admin/static_pages_controller.rb +1 -3
- data/app/controllers/admin/structures_controller.rb +2 -7
- data/app/controllers/admin/users_controller.rb +1 -1
- data/app/views/ab_admin/devise/sessions/new.html.slim +3 -3
- data/app/views/admin/base/_search_layout.html.slim +3 -1
- data/app/views/admin/base/_table.html.slim +1 -1
- data/app/views/admin/base/update.js.erb +3 -1
- data/app/views/admin/locators/show.html.slim +22 -1
- data/app/views/admin/manager/_chart.html.slim +4 -0
- data/app/views/admin/manager/_table.html.slim +16 -13
- data/app/views/admin/shared/_action_items.html.slim +12 -0
- data/app/views/admin/shared/_content_actions.html.slim +15 -3
- data/app/views/admin/shared/_locale_tabs.html.slim +5 -3
- data/app/views/admin/shared/_main_menu.html.slim +20 -0
- data/app/views/admin/shared/_save_buttons.html.slim +2 -1
- data/app/views/admin/users/_table.html.slim +6 -0
- data/app/views/layouts/admin/_navigation.html.slim +2 -24
- data/config/locales/de.yml +0 -8
- data/config/locales/en.yml +3 -11
- data/config/locales/it.yml +9 -17
- data/config/locales/ru.yml +0 -8
- data/config/locales/uk.yml +0 -8
- data/config/routes.rb +2 -1
- data/lib/ab_admin.rb +6 -1
- data/lib/ab_admin/abstract_resource.rb +1 -1
- data/lib/ab_admin/carrierwave/base_uploader.rb +1 -1
- data/lib/ab_admin/concerns/utilities.rb +2 -2
- data/lib/ab_admin/config/base.rb +7 -5
- data/lib/ab_admin/core_ext/hash.rb +19 -1
- data/lib/ab_admin/core_ext/other.rb +0 -48
- data/lib/ab_admin/hooks/will_paginate_id_prefetch.rb +1 -1
- data/lib/ab_admin/i18n_tools/model_translator.rb +4 -4
- data/lib/ab_admin/models/asset.rb +0 -4
- data/lib/ab_admin/models/locator.rb +37 -4
- data/lib/ab_admin/models/user.rb +2 -2
- data/lib/ab_admin/utils.rb +1 -1
- data/lib/ab_admin/utils/eval_helpers.rb +1 -5
- data/lib/ab_admin/utils/logger.rb +11 -2
- data/lib/ab_admin/utils/mysql.rb +2 -2
- data/lib/ab_admin/version.rb +1 -1
- data/lib/ab_admin/views/admin_helpers.rb +38 -21
- data/lib/ab_admin/views/admin_navigation_helpers.rb +6 -6
- data/lib/ab_admin/views/form_builder.rb +4 -1
- data/lib/ab_admin/views/helpers.rb +13 -34
- data/lib/ab_admin/views/inputs/date_time_picker_input.rb +5 -4
- data/lib/ab_admin/views/manager_helpers.rb +21 -3
- data/lib/generators/ab_admin/glob/glob_generator.rb +3 -6
- data/lib/generators/ab_admin/install/templates/models/asset.rb +1 -1
- data/lib/generators/ab_admin/install/templates/models/structure_type.rb +4 -0
- data/lib/generators/ab_admin/install/templates/spec/factories/sequences.rb +2 -2
- data/lib/generators/ab_admin/install/templates/spec/factories/structure_factory.rb +1 -1
- data/lib/generators/ab_admin/install/templates/spec/factories/user_factory.rb +1 -1
- data/lib/generators/ab_admin/install/templates/spec/spec_helper.rb +1 -1
- data/lib/generators/ab_admin/install/templates/spec/support/controller_macros.rb +4 -4
- data/lib/generators/template.rb +2 -2
- metadata +51 -39
data/config/locales/ru.yml
CHANGED
data/config/locales/uk.yml
CHANGED
data/config/routes.rb
CHANGED
data/lib/ab_admin.rb
CHANGED
|
@@ -135,6 +135,8 @@ module AbAdmin
|
|
|
135
135
|
mattr_accessor :site_name
|
|
136
136
|
@@site_name = 'AbAdmin'
|
|
137
137
|
|
|
138
|
+
mattr_accessor :root_path
|
|
139
|
+
|
|
138
140
|
mattr_accessor :body_css_class
|
|
139
141
|
|
|
140
142
|
mattr_accessor :favicon_path
|
|
@@ -152,7 +154,7 @@ module AbAdmin
|
|
|
152
154
|
@@translate_models = %w(User Asset Structure StaticPage Header AdminComment)
|
|
153
155
|
|
|
154
156
|
mattr_accessor :assets
|
|
155
|
-
@@assets = %w(ab_admin/devise.css bootstrap.js ab_admin/loading.gif ab_admin/clear.png)
|
|
157
|
+
@@assets = %w(ab_admin/devise.css bootstrap.js ab_admin/loading.gif ab_admin/clear.png ab_admin/clear.png admin/flags/*.png)
|
|
156
158
|
|
|
157
159
|
mattr_accessor :test_settings
|
|
158
160
|
@@test_settings = {}
|
|
@@ -174,6 +176,9 @@ module AbAdmin
|
|
|
174
176
|
|
|
175
177
|
mattr_accessor :base_url
|
|
176
178
|
|
|
179
|
+
mattr_accessor :default_resource_settings
|
|
180
|
+
@@default_resource_settings = {index_view: 'table', search: true, batch: true, hotkeys: true, list_dblclick: true}
|
|
181
|
+
|
|
177
182
|
mattr_accessor :default_per_page
|
|
178
183
|
@@default_per_page = 50
|
|
179
184
|
|
|
@@ -6,7 +6,7 @@ module AbAdmin
|
|
|
6
6
|
ACTIONS = [:index, :show, :new, :edit, :create, :update, :destroy, :preview, :batch, :rebuild, :custom_action, :history]
|
|
7
7
|
end
|
|
8
8
|
|
|
9
|
-
attr_accessor :model, :table, :search, :export, :form, :modal_form, :show, :preview_path, :actions, :custom_settings,
|
|
9
|
+
attr_accessor :model, :table, :search, :export, :form, :chart, :modal_form, :show, :preview_path, :actions, :custom_settings,
|
|
10
10
|
:batch_action_list, :action_items, :disabled_action_items, :resource_action_items, :tree_node_renderer,
|
|
11
11
|
:parent_resources, :custom_actions, :permitted_params, :scopes
|
|
12
12
|
|
|
@@ -47,7 +47,7 @@ module AbAdmin
|
|
|
47
47
|
end
|
|
48
48
|
|
|
49
49
|
def human_full_filename(for_file=filename)
|
|
50
|
-
ext = File.extname(for_file)
|
|
50
|
+
ext = File.extname(for_file)
|
|
51
51
|
human_filename_part = for_file.chomp(ext)
|
|
52
52
|
tech_filename_part = "#{base_filename_part}#{ext}"
|
|
53
53
|
human_filename_part == secure_token ? tech_filename_part : "#{human_filename_part}_#{tech_filename_part}"
|
|
@@ -32,8 +32,8 @@ module AbAdmin
|
|
|
32
32
|
#ActiveRecord::Base.descendants.find_all { |model| model.descends_from_active_record? }
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
def han(attr)
|
|
36
|
-
human_attribute_name(attr)
|
|
35
|
+
def han(attr, locale: nil)
|
|
36
|
+
locale ? "#{human_attribute_name(attr)} (#{locale})" : human_attribute_name(attr)
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def quote_column(col_name)
|
data/lib/ab_admin/config/base.rb
CHANGED
|
@@ -3,8 +3,7 @@ module AbAdmin
|
|
|
3
3
|
class BaseBuilder
|
|
4
4
|
attr_reader :options, :fields
|
|
5
5
|
attr_accessor :partial
|
|
6
|
-
class_attribute :
|
|
7
|
-
self.field_defaults = {}
|
|
6
|
+
class_attribute :partial_name, instance_writer: false
|
|
8
7
|
|
|
9
8
|
def initialize(options={}, &block)
|
|
10
9
|
@fields = []
|
|
@@ -14,7 +13,7 @@ module AbAdmin
|
|
|
14
13
|
end
|
|
15
14
|
|
|
16
15
|
def field(name, options={}, &block)
|
|
17
|
-
@fields << Field.new(name, options
|
|
16
|
+
@fields << Field.new(name, options, &block)
|
|
18
17
|
end
|
|
19
18
|
|
|
20
19
|
def self.default_for_model(model, options={})
|
|
@@ -30,7 +29,6 @@ module AbAdmin
|
|
|
30
29
|
end
|
|
31
30
|
|
|
32
31
|
class Table < BaseBuilder
|
|
33
|
-
self.field_defaults = {sortable: true}
|
|
34
32
|
self.partial_name = 'table'
|
|
35
33
|
end
|
|
36
34
|
|
|
@@ -38,6 +36,10 @@ module AbAdmin
|
|
|
38
36
|
self.partial_name = 'search_form'
|
|
39
37
|
end
|
|
40
38
|
|
|
39
|
+
class Chart < BaseBuilder
|
|
40
|
+
self.partial_name = 'chart'
|
|
41
|
+
end
|
|
42
|
+
|
|
41
43
|
class Export < BaseBuilder
|
|
42
44
|
def render_options
|
|
43
45
|
{column_names: fields.map(&:name), column_data: fields.map(&:data),
|
|
@@ -164,11 +166,11 @@ module AbAdmin
|
|
|
164
166
|
def initialize(name, options={}, &block)
|
|
165
167
|
@name = name
|
|
166
168
|
@options = options
|
|
169
|
+
@options[:badge] = {} if @options[:badge] && !@options[:badge].is_a?(Hash)
|
|
167
170
|
@data = block
|
|
168
171
|
end
|
|
169
172
|
|
|
170
173
|
def apply(relation, params)
|
|
171
|
-
return relation unless params[name].present?
|
|
172
174
|
data.is_a?(Proc) ? data.call(relation, params) : relation.public_send(name)
|
|
173
175
|
end
|
|
174
176
|
end
|
|
@@ -103,10 +103,15 @@ class Hash
|
|
|
103
103
|
new_hash
|
|
104
104
|
end
|
|
105
105
|
|
|
106
|
-
def
|
|
106
|
+
def reject_blank
|
|
107
107
|
reject { |_, v| v.blank? }
|
|
108
108
|
end
|
|
109
109
|
|
|
110
|
+
def no_blank
|
|
111
|
+
ActiveSupport::Deprecation.warn('`no_blank` is deprecated, use `reject_blank` instead')
|
|
112
|
+
reject_blank
|
|
113
|
+
end
|
|
114
|
+
|
|
110
115
|
def try_keys(*try_keys)
|
|
111
116
|
try_keys.each do |k|
|
|
112
117
|
return self[k] if self.has_key?(k)
|
|
@@ -122,4 +127,17 @@ class Hash
|
|
|
122
127
|
}
|
|
123
128
|
end unless Hash.method_defined?(:deep_stringify_keys)
|
|
124
129
|
|
|
130
|
+
def flatten_hash!(k = [])
|
|
131
|
+
inject({}) do |h, v|
|
|
132
|
+
new_k = k + [v[0]]
|
|
133
|
+
h.merge!(v[-1].is_a?(Hash) ? v[-1].flatten_hash!(new_k) : {new_k => v[-1]})
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def flatten_hash(k = [])
|
|
138
|
+
dup.inject({}) do |h, v|
|
|
139
|
+
new_k = k + [v[0]]
|
|
140
|
+
h.merge!(v[-1].is_a?(Hash) ? v[-1].dup.flatten_hash(new_k) : {new_k => v[-1]})
|
|
141
|
+
end
|
|
142
|
+
end
|
|
125
143
|
end
|
|
@@ -4,16 +4,6 @@ class NilClass
|
|
|
4
4
|
end
|
|
5
5
|
end
|
|
6
6
|
|
|
7
|
-
class Time
|
|
8
|
-
def formatted_datetime
|
|
9
|
-
I18n.l(self, format: '%d.%m.%Y %H:%M')
|
|
10
|
-
end
|
|
11
|
-
|
|
12
|
-
def formatted_date
|
|
13
|
-
I18n.l(self, format: '%d.%m.%Y')
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
|
|
17
7
|
class TrueClass
|
|
18
8
|
def to_i
|
|
19
9
|
1
|
|
@@ -37,41 +27,3 @@ class Date
|
|
|
37
27
|
self.to_date == ::Date.tomorrow
|
|
38
28
|
end
|
|
39
29
|
end
|
|
40
|
-
|
|
41
|
-
#module ActiveSupport
|
|
42
|
-
# class OrderedHash < ::Hash
|
|
43
|
-
# def to_yaml(opts = {})
|
|
44
|
-
# YAML::quick_emit(self, opts) do |out|
|
|
45
|
-
# out.map(nil, to_yaml_style) do |map|
|
|
46
|
-
# each do |k, v|
|
|
47
|
-
# map.add(k, v)
|
|
48
|
-
# end
|
|
49
|
-
# end
|
|
50
|
-
# end
|
|
51
|
-
# end
|
|
52
|
-
# end
|
|
53
|
-
#end
|
|
54
|
-
|
|
55
|
-
#class Numeric
|
|
56
|
-
# # round a given number to the nearest step
|
|
57
|
-
# def round_by(increment)
|
|
58
|
-
# (self /increment).round * increment
|
|
59
|
-
# end
|
|
60
|
-
#end
|
|
61
|
-
#
|
|
62
|
-
#class Float
|
|
63
|
-
# def ceil_to(i=4)
|
|
64
|
-
# #(self * 10**i).ceil.to_f / 10**i
|
|
65
|
-
# (self * (10.0 ** i)).round(10).ceil * (10.0 ** (-i))
|
|
66
|
-
# end
|
|
67
|
-
#
|
|
68
|
-
# def floor_to(i=4)
|
|
69
|
-
# (self * 10**i).floor.to_f / 10**i
|
|
70
|
-
# end
|
|
71
|
-
#
|
|
72
|
-
# def round_to
|
|
73
|
-
# return (self+0.5).floor if self > 0.0
|
|
74
|
-
# return (self-0.5).ceil if self < 0.0
|
|
75
|
-
# 0
|
|
76
|
-
# end
|
|
77
|
-
#end
|
|
@@ -40,7 +40,7 @@ module WillPaginate
|
|
|
40
40
|
rel.total_entries = total.to_i unless total.blank?
|
|
41
41
|
|
|
42
42
|
if large
|
|
43
|
-
ids = rel.except(:includes).pluck("#{quoted_table_name}.id")
|
|
43
|
+
ids = rel.except(:includes).pluck(Arel.sql("#{quoted_table_name}.id"))
|
|
44
44
|
new_rel = rel.except(:limit, :offset, :where).where(id: ids)
|
|
45
45
|
new_rel.paginate_limit = rel.limit_value.to_i
|
|
46
46
|
new_rel.paginate_offset = rel.offset_value.to_i
|
|
@@ -5,7 +5,8 @@ module AbAdmin
|
|
|
5
5
|
IGNORE_COLUMNS = %w(id reset_password_sent_at remember_created_at current_sign_in_at confirmation_token
|
|
6
6
|
reset_password_token password_salt failed_attempts)
|
|
7
7
|
|
|
8
|
-
def initialize
|
|
8
|
+
def initialize(options: {})
|
|
9
|
+
@options = options
|
|
9
10
|
@locales = Globalize.available_locales
|
|
10
11
|
@models = AbAdmin.translate_models.map{|m| m.constantize }
|
|
11
12
|
@models_i18n_hash = {}
|
|
@@ -33,10 +34,9 @@ module AbAdmin
|
|
|
33
34
|
model.reflect_on_all_associations.map(&:name).map(&:to_s).reject { |a| a =~ /^translation/ }.each do |assoc|
|
|
34
35
|
o[assoc] = ha(model, assoc, locale)
|
|
35
36
|
end
|
|
36
|
-
if model.new.respond_to?("#{attr}_#{locale.to_s}".to_sym)
|
|
37
|
+
if @options[:locale_attributes] && model.new.respond_to?("#{attr}_#{locale.to_s}".to_sym)
|
|
37
38
|
@locales.each do |locale_1|
|
|
38
|
-
|
|
39
|
-
o["#{attr}_#{locale_1.to_s}"] = "#{ha(model, attr, locale)} (#{attr_suffix})"
|
|
39
|
+
o["#{attr}_#{locale_1.to_s}"] = "#{ha(model, attr, locale)} (#{locale_1.to_s})"
|
|
40
40
|
end
|
|
41
41
|
end
|
|
42
42
|
end.sort.to_h
|
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
require 'csv'
|
|
2
|
+
|
|
1
3
|
module AbAdmin
|
|
2
4
|
module Models
|
|
3
5
|
module Locator
|
|
@@ -23,13 +25,44 @@ module AbAdmin
|
|
|
23
25
|
def prepare_data(path)
|
|
24
26
|
data = YAML.load_file(path)
|
|
25
27
|
locale = data.keys.first
|
|
26
|
-
OpenStruct.new({locale: locale.to_sym, data: data[locale], flat_data:
|
|
28
|
+
OpenStruct.new({locale: locale.to_sym, data: data[locale], flat_data: data[locale].flatten_hash,
|
|
27
29
|
filename: File.basename(path), path: path, dir: File.dirname(path)})
|
|
28
30
|
end
|
|
29
31
|
|
|
30
|
-
def
|
|
31
|
-
return
|
|
32
|
-
|
|
32
|
+
def export_csv(*keys, locales: nil)
|
|
33
|
+
return if keys.blank?
|
|
34
|
+
locales ||= I18n.available_locales
|
|
35
|
+
I18n.backend.available_locales # Force load translations
|
|
36
|
+
filter_keys = keys.map {|k| k.include?('*') ? Regexp.new("\\A#{k.gsub('.', '\.').gsub('*', '.*')}\\z") : k}
|
|
37
|
+
data = filter_keys.each_with_object(Hash.new { |h, k| h[k] = [] }) do |key, res|
|
|
38
|
+
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}
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
for_csv = [['DO NOT EDIT THIS COLUMN!', *locales]] + data.map{|k, v| [k, *v] }
|
|
43
|
+
for_csv.map(&:to_csv).join
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
def import_csv(csv, locales: nil)
|
|
47
|
+
return if csv.blank?
|
|
48
|
+
locales ||= I18n.available_locales
|
|
49
|
+
csv_data = CSV.parse(csv)
|
|
50
|
+
csv_data.shift.each_with_index do |l, i|
|
|
51
|
+
next if i.zero? || !locales.include?(l.to_sym)
|
|
52
|
+
path = Rails.root.join('config', 'locales', "#{l}.yml")
|
|
53
|
+
raise "Missing file #{path}" unless File.file?(path)
|
|
54
|
+
data = YAML.load_file(path)
|
|
55
|
+
csv_data.each do |d|
|
|
56
|
+
key_parts = [l.to_s] + d[0].split('.')
|
|
57
|
+
raise "Invalid key #{d[0]}" unless data.dig(*key_parts)
|
|
58
|
+
data.store_multi(d[i], *key_parts)
|
|
59
|
+
end
|
|
60
|
+
save path, data
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def translations
|
|
65
|
+
@translations ||= I18n.backend.send(:translations).slice(*I18n.available_locales).transform_values{|v| v.flatten_hash.transform_keys{|k| k.join('.') } }
|
|
33
66
|
end
|
|
34
67
|
end
|
|
35
68
|
|
data/lib/ab_admin/models/user.rb
CHANGED
data/lib/ab_admin/utils.rb
CHANGED
|
@@ -9,7 +9,7 @@ module AbAdmin
|
|
|
9
9
|
Kernel.suppress_warnings do
|
|
10
10
|
Dir.glob(Rails.root.to_s + '/app/models/**/*.rb').reject { |path| path =~ /concerns|shared/ }.each { |file| require file }
|
|
11
11
|
end
|
|
12
|
-
ActiveRecord::Base.
|
|
12
|
+
[ActiveRecord::Base, ApplicationRecord].flat_map{|sc| sc.subclasses.find_all { |model| model.connection.table_exists?(model.table_name) } }
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
def load_files!(base_path = 'lib/utils')
|
|
@@ -90,11 +90,7 @@ module AbAdmin
|
|
|
90
90
|
when Symbol, String
|
|
91
91
|
obj.send(symbol_or_proc.to_sym, *options[:attrs])
|
|
92
92
|
when Proc
|
|
93
|
-
|
|
94
|
-
obj.instance_exec(&symbol_or_proc)
|
|
95
|
-
else
|
|
96
|
-
symbol_or_proc.call(obj)
|
|
97
|
-
end
|
|
93
|
+
exec ? obj.instance_exec(&symbol_or_proc) : symbol_or_proc.call(obj)
|
|
98
94
|
end
|
|
99
95
|
end
|
|
100
96
|
|
|
@@ -4,7 +4,7 @@ module AbAdmin
|
|
|
4
4
|
class ExtendedLogger < ::Logger
|
|
5
5
|
def exception(e, options={})
|
|
6
6
|
message = "#{e.message} #{"DATA:#{options[:data].inspect}" if options && options[:data]}"
|
|
7
|
-
backtrace = e.backtrace.map { |l| "#{' ' * 2}#{l}" }.join("\n")
|
|
7
|
+
backtrace = e.backtrace.map { |l| "#{' ' * 2}#{l}" }.join("\n") if e.backtrace
|
|
8
8
|
error("#{e.class} #{message}\n#{backtrace}\n\n")
|
|
9
9
|
end
|
|
10
10
|
|
|
@@ -13,9 +13,18 @@ module AbAdmin
|
|
|
13
13
|
end
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
+
class Formatter
|
|
17
|
+
FORMAT = "[%s] %5s %s\n".freeze
|
|
18
|
+
DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%3N'.freeze
|
|
19
|
+
|
|
20
|
+
def call(severity, time, _, msg)
|
|
21
|
+
FORMAT % [time.strftime(DATETIME_FORMAT), severity, msg]
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
|
|
16
25
|
def self.for_file(filename)
|
|
17
26
|
logger = ExtendedLogger.new(Rails.root.join('log', filename))
|
|
18
|
-
logger.formatter =
|
|
27
|
+
logger.formatter = Formatter.new
|
|
19
28
|
logger
|
|
20
29
|
end
|
|
21
30
|
end
|
data/lib/ab_admin/utils/mysql.rb
CHANGED
|
@@ -13,10 +13,10 @@ module AbAdmin
|
|
|
13
13
|
end
|
|
14
14
|
|
|
15
15
|
# remove duplicate records by columns
|
|
16
|
-
def remove_duplicates(*cols)
|
|
16
|
+
def remove_duplicates(*cols, deleted_id_order: '<')
|
|
17
17
|
conds = cols.map { |col| "#{table_name}.#{col} IS NOT NULL AND #{table_name}.#{col} = t.#{col}" }.join(' AND ')
|
|
18
18
|
query = <<-SQL
|
|
19
|
-
DELETE FROM #{table_name} USING #{table_name}, #{table_name} AS t WHERE #{table_name}.id
|
|
19
|
+
DELETE FROM #{table_name} USING #{table_name}, #{table_name} AS t WHERE #{table_name}.id #{deleted_id_order} t.id AND #{conds}
|
|
20
20
|
SQL
|
|
21
21
|
connection.execute(query)
|
|
22
22
|
end
|
data/lib/ab_admin/version.rb
CHANGED
|
@@ -21,34 +21,52 @@ module AbAdmin
|
|
|
21
21
|
end
|
|
22
22
|
end
|
|
23
23
|
|
|
24
|
+
def editable_bool(item, attr)
|
|
25
|
+
url = "/admin/#{item.class.model_name.plural}/#{item.id}"
|
|
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
|
|
29
|
+
end
|
|
30
|
+
|
|
24
31
|
def admin_editable(item, attr, options=nil)
|
|
25
32
|
options = {} unless options.is_a?(Hash)
|
|
26
|
-
options[:
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
options[:
|
|
34
|
-
options[:value] ||= item[attr] ? 1 : 0
|
|
35
|
-
options[:title] ||= item[attr] ? 'yes' : 'no'
|
|
36
|
-
when /description|body|content/
|
|
37
|
-
options[:type] ||= 'textarea'
|
|
33
|
+
title = options[:title] || item[attr]
|
|
34
|
+
html_title = admin_pretty_data(title).to_s.html_safe
|
|
35
|
+
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
|
+
|
|
38
|
+
unless options[:type]
|
|
39
|
+
if options[:source]
|
|
40
|
+
options[:type] = 'select'
|
|
38
41
|
else
|
|
39
|
-
|
|
42
|
+
case attr.to_s
|
|
43
|
+
when /_at$/
|
|
44
|
+
options[:type] ||= 'date'
|
|
45
|
+
options[:title] ||= html_title
|
|
46
|
+
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'
|
|
51
|
+
when /description|body|content/
|
|
52
|
+
options[:type] ||= 'textarea'
|
|
53
|
+
else
|
|
54
|
+
options[:type] ||= 'text'
|
|
55
|
+
end
|
|
56
|
+
end
|
|
40
57
|
end
|
|
41
58
|
|
|
42
59
|
data = {
|
|
43
60
|
type: options[:type],
|
|
44
61
|
source: options[:source].try(:to_json),
|
|
45
62
|
model: options[:model] || item.class.model_name.singular,
|
|
63
|
+
accept: options[:accept],
|
|
46
64
|
url: options[:url] || "/admin/#{item.class.model_name.plural}/#{item.id}",
|
|
47
65
|
name: attr,
|
|
48
66
|
value: options[:value] || item[attr],
|
|
49
67
|
title: options[:title] || item[attr]
|
|
50
68
|
}
|
|
51
|
-
link_to
|
|
69
|
+
link_to html_title, '#', class: "editable #{options[:class]}", data: data.update(options[:data] || {})
|
|
52
70
|
end
|
|
53
71
|
|
|
54
72
|
def options_for_ckeditor(options = {})
|
|
@@ -86,8 +104,11 @@ module AbAdmin
|
|
|
86
104
|
render 'admin/admin_comments/comments'
|
|
87
105
|
end
|
|
88
106
|
|
|
89
|
-
def color_bool(val,
|
|
90
|
-
|
|
107
|
+
def color_bool(val, options={})
|
|
108
|
+
options.reverse_merge!(true_css: 'badge-success', false_css: nil, nil_css: nil)
|
|
109
|
+
css = options["#{val.inspect}_css".to_sym]
|
|
110
|
+
text = val.nil? ? '?' : (val ? '+' : '-')
|
|
111
|
+
%(<span class="badge #{css}">#{text}</span>).html_safe
|
|
91
112
|
end
|
|
92
113
|
|
|
93
114
|
def icon(name, white=false)
|
|
@@ -156,11 +177,7 @@ module AbAdmin
|
|
|
156
177
|
when Symbol, String
|
|
157
178
|
obj.send(symbol_or_proc.to_sym)
|
|
158
179
|
when Proc
|
|
159
|
-
|
|
160
|
-
instance_exec(obj, &symbol_or_proc)
|
|
161
|
-
else
|
|
162
|
-
symbol_or_proc.call(obj)
|
|
163
|
-
end
|
|
180
|
+
exec ? instance_exec(obj, &symbol_or_proc) : symbol_or_proc.call(obj)
|
|
164
181
|
end
|
|
165
182
|
end
|
|
166
183
|
|