ab_admin 0.7.0 → 0.8.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
|