ab_admin 0.8.3 → 0.10.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (151) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +11 -5
  4. data/app/assets/javascripts/ab_admin/components/admin_assets.js.coffee +0 -25
  5. data/app/assets/javascripts/ab_admin/components/google_translate.js.coffee +3 -5
  6. data/app/assets/javascripts/ab_admin/components/in_place_edit.js.coffee +33 -25
  7. data/app/assets/javascripts/ab_admin/core/batch_actions.js.coffee +1 -1
  8. data/app/assets/javascripts/ab_admin/core/columns_hider.js.coffee +24 -23
  9. data/app/assets/javascripts/ab_admin/core/init.js.coffee +7 -2
  10. data/app/assets/javascripts/ab_admin/core/search_form.js.coffee +1 -7
  11. data/app/assets/javascripts/ab_admin/core/ui_utils.js.coffee +23 -7
  12. data/app/assets/javascripts/ab_admin/core/utils.js.coffee +16 -2
  13. data/app/assets/javascripts/ab_admin/inputs/datetime_input.js.coffee +1 -0
  14. data/app/assets/javascripts/ab_admin/main.js +3 -4
  15. data/app/assets/stylesheets/ab_admin/bootstrap_and_overrides.scss +71 -25
  16. data/app/assets/stylesheets/ab_admin/components/_base.scss +21 -1
  17. data/app/assets/stylesheets/ab_admin/components/_colored_tabs.scss +1 -1
  18. data/app/assets/stylesheets/ab_admin/components/_form.scss +16 -18
  19. data/app/assets/stylesheets/ab_admin/components/_grid_view.scss +2 -2
  20. data/app/assets/stylesheets/ab_admin/components/_locale_tabs.scss +11 -23
  21. data/app/assets/stylesheets/ab_admin/components/_navigation.scss +7 -11
  22. data/app/assets/stylesheets/ab_admin/components/_table_view.scss +85 -11
  23. data/app/assets/stylesheets/ab_admin/components/_tooltip.scss +81 -0
  24. data/app/assets/stylesheets/ab_admin/components/_tree_view.scss +1 -1
  25. data/app/assets/stylesheets/ab_admin/devise.scss +2 -2
  26. data/app/assets/stylesheets/ab_admin/fileupload.scss +2 -9
  27. data/app/assets/stylesheets/ab_admin/main.scss +1 -2
  28. data/app/controllers/admin/assets_controller.rb +1 -1
  29. data/app/controllers/admin/base_controller.rb +133 -149
  30. data/app/controllers/admin/dashboards_controller.rb +2 -2
  31. data/app/controllers/admin/locators_controller.rb +8 -6
  32. data/app/controllers/admin/manager_controller.rb +19 -49
  33. data/app/controllers/admin/static_pages_controller.rb +0 -4
  34. data/app/controllers/admin/structures_controller.rb +2 -2
  35. data/app/views/ab_admin/devise/sessions/new.html.slim +2 -0
  36. data/app/views/admin/assets/batch_edit.html.slim +3 -2
  37. data/app/views/admin/base/_search_layout.html.slim +7 -6
  38. data/app/views/admin/base/create.js.erb +6 -3
  39. data/app/views/admin/base/edit.js.erb +1 -1
  40. data/app/views/admin/base/index.html.slim +4 -4
  41. data/app/views/admin/base/new.js.erb +1 -1
  42. data/app/views/admin/base/update.js.erb +7 -2
  43. data/app/views/admin/fileupload/_asset_templates.html.slim +1 -2
  44. data/app/views/admin/fileupload/_image.html.slim +1 -2
  45. data/app/views/admin/locators/edit.html.slim +7 -6
  46. data/app/views/admin/manager/_map.html.slim +4 -0
  47. data/app/views/admin/manager/_show_table.html.slim +1 -1
  48. data/app/views/admin/manager/_stats.html.slim +4 -0
  49. data/app/views/admin/manager/_table.html.slim +7 -4
  50. data/app/views/admin/shared/_content_actions.html.slim +35 -30
  51. data/app/views/admin/shared/_flash.html.slim +5 -4
  52. data/app/views/admin/shared/_locale_tabs.html.slim +2 -2
  53. data/app/views/admin/shared/_main_menu.html.slim +1 -1
  54. data/app/views/admin/shared/_save_buttons.html.slim +10 -1
  55. data/app/views/admin/structures/_form.html.slim +1 -1
  56. data/app/views/admin/users/_form.html.slim +3 -3
  57. data/app/views/admin/users/_search_form.html.slim +1 -1
  58. data/app/views/layouts/admin/_footer.html.slim +0 -1
  59. data/app/views/layouts/admin/_navigation.html.slim +1 -1
  60. data/app/views/layouts/admin/application.html.slim +2 -2
  61. data/config/locales/de.yml +1 -2
  62. data/config/locales/en.yml +9 -15
  63. data/config/locales/it.yml +1 -0
  64. data/config/locales/ru.yml +0 -1
  65. data/config/locales/uk.yml +0 -1
  66. data/db/migrate/20130101000001_create_users.rb +1 -4
  67. data/db/migrate/20130101000003_create_assets.rb +1 -1
  68. data/db/migrate/20130101000004_create_headers.rb +5 -5
  69. data/db/migrate/20130101000005_create_static_pages.rb +2 -5
  70. data/db/migrate/20130101000006_create_structures.rb +1 -1
  71. data/db/migrate/20130101000007_base_translations.rb +43 -12
  72. data/db/migrate/20130101000008_create_admin_comments.rb +2 -7
  73. data/db/migrate/20130101000009_create_tracks.rb +4 -8
  74. data/lib/ab_admin/abstract_resource.rb +6 -5
  75. data/lib/ab_admin/carrierwave/base_uploader.rb +87 -75
  76. data/lib/ab_admin/carrierwave/glue.rb +0 -5
  77. data/lib/ab_admin/concerns/admin_addition.rb +15 -27
  78. data/lib/ab_admin/concerns/translations_macro.rb +97 -0
  79. data/lib/ab_admin/concerns/utilities.rb +2 -2
  80. data/lib/ab_admin/config/base.rb +27 -4
  81. data/lib/ab_admin/controllers/callbacks.rb +3 -26
  82. data/lib/ab_admin/core_ext/array.rb +1 -50
  83. data/lib/ab_admin/core_ext/hash.rb +2 -31
  84. data/lib/ab_admin/core_ext/other.rb +0 -6
  85. data/lib/ab_admin/core_ext/string.rb +1 -86
  86. data/lib/ab_admin/devise.rb +7 -0
  87. data/lib/ab_admin/engine.rb +2 -1
  88. data/lib/ab_admin/hooks/ckeditor_lazy.rb +13 -0
  89. data/lib/ab_admin/hooks/will_paginate_id_prefetch.rb +8 -6
  90. data/lib/ab_admin/hooks/will_paginate_no_uri.rb +1 -1
  91. data/lib/ab_admin/i18n_tools/google_translate.rb +3 -1
  92. data/lib/ab_admin/i18n_tools/model_translator.rb +1 -1
  93. data/lib/ab_admin/menu/base_group.rb +0 -1
  94. data/lib/ab_admin/menu/group.rb +2 -4
  95. data/lib/ab_admin/menu/item.rb +4 -8
  96. data/lib/ab_admin/models/asset.rb +7 -10
  97. data/lib/ab_admin/models/header.rb +2 -2
  98. data/lib/ab_admin/models/locator.rb +29 -3
  99. data/lib/ab_admin/models/settings.rb +2 -2
  100. data/lib/ab_admin/models/structure.rb +3 -3
  101. data/lib/ab_admin/models/track.rb +15 -3
  102. data/lib/ab_admin/models/user.rb +12 -48
  103. data/lib/ab_admin/utils/csv_document.rb +8 -6
  104. data/lib/ab_admin/utils/eval_helpers.rb +0 -13
  105. data/lib/ab_admin/utils/logger.rb +12 -2
  106. data/lib/ab_admin/utils/mysql.rb +2 -3
  107. data/lib/ab_admin/utils/xls_document.rb +18 -18
  108. data/lib/ab_admin/utils.rb +0 -5
  109. data/lib/ab_admin/version.rb +1 -1
  110. data/lib/ab_admin/views/admin_helpers.rb +43 -28
  111. data/lib/ab_admin/views/admin_navigation_helpers.rb +18 -16
  112. data/lib/ab_admin/views/form_builder.rb +7 -5
  113. data/lib/ab_admin/views/helpers.rb +0 -9
  114. data/lib/ab_admin/views/inputs/ckeditor_input.rb +1 -5
  115. data/lib/ab_admin/views/manager_helpers.rb +15 -6
  116. data/lib/ab_admin/views/search_form_builder.rb +13 -13
  117. data/lib/ab_admin/views/will_paginate_bootstrap_renderer.rb +60 -0
  118. data/lib/ab_admin.rb +44 -32
  119. data/lib/generators/ab_admin/glob/glob_generator.rb +4 -5
  120. data/lib/generators/ab_admin/glob/templates/migration.erb +10 -7
  121. data/lib/generators/ab_admin/install/templates/config/ab_admin.rb.erb +1 -1
  122. data/lib/generators/ab_admin/install/templates/models/user.rb +1 -13
  123. data/lib/generators/ab_admin/install/templates/spec/spec_helper.rb +0 -1
  124. data/lib/generators/ab_admin/install/templates/spec/support/database_cleaner.rb +8 -11
  125. data/lib/generators/ab_admin/install/templates/uploaders/attachment_file_uploader.rb +1 -1
  126. data/lib/generators/ab_admin/install/templates/uploaders/avatar_uploader.rb +1 -1
  127. data/lib/generators/ab_admin/install/templates/uploaders/picture_uploader.rb +16 -3
  128. data/lib/generators/ab_admin/model/model_generator.rb +3 -4
  129. data/lib/generators/ab_admin/model/templates/resource.erb +5 -2
  130. data/lib/generators/ab_admin/resource/resource_generator.rb +0 -4
  131. data/lib/generators/ab_admin/resource/templates/controller.erb +2 -9
  132. data/lib/tasks/assets.rake +5 -5
  133. metadata +45 -85
  134. data/app/assets/images/admin/Jcrop.gif +0 -0
  135. data/app/assets/images/admin/flags/de.png +0 -0
  136. data/app/assets/images/admin/flags/en.png +0 -0
  137. data/app/assets/images/admin/flags/es.png +0 -0
  138. data/app/assets/images/admin/flags/fr.png +0 -0
  139. data/app/assets/images/admin/flags/it.png +0 -0
  140. data/app/assets/images/admin/flags/ja.png +0 -0
  141. data/app/assets/images/admin/flags/pl.png +0 -0
  142. data/app/assets/images/admin/flags/ru.png +0 -0
  143. data/app/assets/images/admin/flags/uk.png +0 -0
  144. data/app/assets/javascripts/ab_admin/components/croppable_image.js.coffee +0 -33
  145. data/app/assets/stylesheets/ab_admin/components/_columns_hider.scss +0 -5
  146. data/app/assets/stylesheets/ab_admin/components/_perms.scss +0 -39
  147. data/app/views/admin/shared/_columns_hider.html.slim +0 -9
  148. data/lib/ab_admin/hooks/globalize_locale_suffix_accessors.rb +0 -25
  149. data/lib/ab_admin/hooks/globalize_valid_locale.rb +0 -9
  150. data/lib/generators/ab_admin/ckeditor_assets/ckeditor_assets_generator.rb +0 -19
  151. data/lib/generators/template.rb +0 -96
@@ -6,17 +6,14 @@ module AbAdmin
6
6
  included do
7
7
  has_one :avatar, as: :assetable, dependent: :destroy, autosave: true
8
8
 
9
- scope :managers, -> { where(user_role_id: [::UserRoleType.admin.id, ::UserRoleType.moderator.id]) }
10
9
  scope :active, -> { where(locked_at: nil) }
11
10
  scope :admin, proc { includes(:avatar) }
12
11
 
13
- after_initialize :init
14
- before_validation :generate_login
15
- before_validation :set_default_role, unless: :user_role_id?
16
-
17
- validate :check_role
18
-
19
12
  enumerated_attribute :user_role_type, id_attribute: :user_role_id, class: ::UserRoleType
13
+ delegate *UserRoleType.codes.map{|code| "#{code}?" }, to: :user_role_type
14
+ end
15
+
16
+ def admin_menu_builder
20
17
  end
21
18
 
22
19
  def name
@@ -40,6 +37,10 @@ module AbAdmin
40
37
  active_for_authentication?
41
38
  end
42
39
 
40
+ def admin_access?
41
+ admin? || moderator?
42
+ end
43
+
43
44
  def generate_password!
44
45
  raw_password = AbAdmin.test_env? ? '654321' : AbAdmin.friendly_token
45
46
  self.password = self.password_confirmation = raw_password
@@ -47,47 +48,10 @@ module AbAdmin
47
48
  raw_password
48
49
  end
49
50
 
50
- def admin_access?
51
- moderator?
52
- end
53
-
54
- def default?
55
- has_role?(:default)
56
- end
57
-
58
- def redactor?
59
- has_role?(:redactor)
60
- end
61
-
62
- def moderator?
63
- has_role?(:admin) || has_role?(:moderator)
64
- end
65
-
66
- def admin?
67
- has_role?(:admin)
68
- end
69
-
70
- def has_role?(role_name)
71
- user_role_type.code == role_name
72
- end
73
-
74
- def set_default_role
75
- self.user_role_id ||= ::UserRoleType.default.id
76
- end
77
-
78
- protected
79
-
80
- def generate_login
81
- self.login ||= begin
82
- unless email.blank?
83
- tmp_login = email.split('@').first
84
- tmp_login.parameterize.downcase.gsub(/[^A-Za-z0-9-]+/, '-').gsub(/-+/, '-')
85
- end
86
- end
87
- end
88
-
89
- def check_role
90
- errors.add(:user_role_id, :invalid) unless ::UserRoleType.valid?(user_role_id)
51
+ def password_required?
52
+ return true if password.present?
53
+ return false if persisted? && password.blank?
54
+ super
91
55
  end
92
56
  end
93
57
  end
@@ -3,8 +3,6 @@ require 'csv'
3
3
  module AbAdmin
4
4
  module Utils
5
5
  class CsvDocument
6
- include AbAdmin::Utils::EvalHelpers
7
-
8
6
  def initialize(source, options = {})
9
7
  @source = source
10
8
  @options = options
@@ -27,12 +25,17 @@ module AbAdmin
27
25
  @filename ||= [@options[:filename] || "#{@klass.model_name.plural}-#{Time.now.strftime('%Y-%m-%d')}", '.csv'].join
28
26
  end
29
27
 
30
- def render
28
+ def render(context=nil, options={})
31
29
  ::CSV.generate(col_sep: @options[:column_separator] || ',') do |csv|
32
30
  csv << columns_names
33
31
 
34
- each_record do |item|
35
- csv << column_data.map { |column| AbAdmin.pretty_data call_method_or_proc_on(item, column, exec: false) }
32
+ I18n.with_locale options[:locale] do
33
+ each_record do |item|
34
+ csv << column_data.map do |column|
35
+ value = column.is_a?(Symbol) ? item.public_send(column) : context.instance_exec(item, &column)
36
+ AbAdmin.pretty_data value
37
+ end
38
+ end
36
39
  end
37
40
  end
38
41
  end
@@ -60,7 +63,6 @@ module AbAdmin
60
63
  @source.class
61
64
  end
62
65
  end
63
-
64
66
  end
65
67
  end
66
68
  end
@@ -83,19 +83,6 @@ module AbAdmin
83
83
  raise ArgumentError, 'Methods must be a symbol denoting the method to call, a block to be invoked, or a string to be evaluated'
84
84
  end
85
85
  end
86
-
87
- def call_method_or_proc_on(obj, symbol_or_proc, options = {})
88
- exec = options[:exec].nil? ? true : options[:exec]
89
- case symbol_or_proc
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])
95
- when Proc
96
- exec ? obj.instance_exec(&symbol_or_proc) : symbol_or_proc.call(obj)
97
- end
98
- end
99
86
  end
100
87
  end
101
88
  end
@@ -8,11 +8,21 @@ module AbAdmin
8
8
  error("#{e.class} #{message}\n#{backtrace}\n\n")
9
9
  end
10
10
 
11
+ def puts(msg)
12
+ debug msg
13
+ end
14
+
11
15
  def reopen
12
16
  @logdev = LogDevice.new(@logdev.filename)
13
17
  end
14
18
  end
15
19
 
20
+ class BasicFormatter
21
+ def call(severity, time, _, msg)
22
+ "#{msg}\n"
23
+ end
24
+ end
25
+
16
26
  class Formatter
17
27
  FORMAT = "[%s] %5s %s\n".freeze
18
28
  DATETIME_FORMAT = '%Y-%m-%dT%H:%M:%S.%3N'.freeze
@@ -22,9 +32,9 @@ module AbAdmin
22
32
  end
23
33
  end
24
34
 
25
- def self.for_file(filename)
35
+ def self.for_file(filename, formatter: nil)
26
36
  logger = ExtendedLogger.new(Rails.root.join('log', filename))
27
- logger.formatter = Formatter.new
37
+ logger.formatter = formatter || Formatter.new
28
38
  logger
29
39
  end
30
40
  end
@@ -14,14 +14,13 @@ module AbAdmin
14
14
 
15
15
  # remove duplicate records by columns
16
16
  def remove_duplicates(*cols, deleted_id_order: '<')
17
- conds = cols.map { |col| "#{table_name}.#{col} IS NOT NULL AND #{table_name}.#{col} = t.#{col}" }.join(' AND ')
17
+ condition_sql = 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 #{deleted_id_order} t.id AND #{conds}
19
+ DELETE FROM #{table_name} USING #{table_name}, #{table_name} AS t WHERE #{table_name}.id #{deleted_id_order} t.id AND #{condition_sql}
20
20
  SQL
21
21
  connection.execute(query)
22
22
  end
23
23
 
24
-
25
24
  # Disables key updates for model table
26
25
  def disable_keys
27
26
  connection.execute("ALTER TABLE #{quoted_table_name} DISABLE KEYS")
@@ -12,8 +12,6 @@ module AbAdmin
12
12
  end
13
13
 
14
14
  class XlsDocument
15
- include AbAdmin::Utils::EvalHelpers
16
-
17
15
  def initialize(source, options = {})
18
16
  @source = source
19
17
  @options = options
@@ -49,25 +47,27 @@ module AbAdmin
49
47
  @filename ||= [@options[:filename] || "#{@klass.model_name.plural}-#{Time.now.strftime('%Y-%m-%d')}", '.xlsx'].join
50
48
  end
51
49
 
52
- def render
50
+ def render(context, options={})
53
51
  date_format = workbook.add_format(num_format: 'dd.mm.yyyy')
54
52
  time_format = workbook.add_format(num_format: 'dd.mm.yyyy HH:MM')
55
53
 
56
- each_with_index do |item, index|
57
- row = index + 1
58
-
59
- column_data.each_with_index do |column, num|
60
- value = call_method_or_proc_on(item, column, exec: false)
61
-
62
- case value
63
- when Date
64
- worksheet.write_string(row, num, value.strftime('%Y-%m-%dT'), date_format)
65
- when DateTime, Time
66
- worksheet.write_date_time(row, num, value.strftime('%Y-%m-%dT%H:%M:%S.%L'), time_format)
67
- when String
68
- worksheet.write_string(row, num, value)
69
- else
70
- worksheet.write(row, num, AbAdmin.pretty_data(value))
54
+ I18n.with_locale options[:locale] do
55
+ each_with_index do |item, index|
56
+ row = index + 1
57
+
58
+ column_data.each_with_index do |column, num|
59
+ value = column.is_a?(Symbol) ? item.public_send(column) : context.instance_exec(item, &column)
60
+
61
+ case value
62
+ when Date
63
+ worksheet.write_string(row, num, value.strftime('%Y-%m-%dT'), date_format)
64
+ when DateTime, Time
65
+ worksheet.write_date_time(row, num, value.strftime('%Y-%m-%dT%H:%M:%S.%L'), time_format)
66
+ when String
67
+ worksheet.write_string(row, num, value)
68
+ else
69
+ worksheet.write(row, num, AbAdmin.pretty_data(value))
70
+ end
71
71
  end
72
72
  end
73
73
  end
@@ -1,10 +1,5 @@
1
1
  module AbAdmin
2
2
  module Utils
3
- autoload :CSVBuilder, 'ab_admin/utils/csv_builder'
4
- autoload :EvalHelpers, 'ab_admin/utils/eval_helpers'
5
- autoload :Logger, 'ab_admin/utils/logger'
6
- autoload :Mysql, 'ab_admin/utils/mysql'
7
-
8
3
  def all_models
9
4
  Kernel.suppress_warnings do
10
5
  Dir.glob(Rails.root.to_s + '/app/models/**/*.rb').reject { |path| path =~ /concerns|shared/ }.each { |file| require file }
@@ -1,3 +1,3 @@
1
1
  module AbAdmin
2
- VERSION = '0.8.3'
2
+ VERSION = '0.10.0'
3
3
  end
@@ -1,14 +1,16 @@
1
1
  module AbAdmin
2
2
  module Views
3
3
  module AdminHelpers
4
-
5
4
  def admin_form_for(object, *args, &block)
6
5
  record = Array(object).last
7
6
  record.fallbacks_for_empty_translations = false if record.respond_to?(:fallbacks_for_empty_translations)
8
7
  options = args.extract_options!
8
+ options[:wrapper] = :bootstrap
9
9
  options[:remote] = true if request.xhr?
10
10
  options[:html] ||= {}
11
- options[:html][:class] ||= 'form-horizontal'
11
+ options[:html][:class] = Array(options[:html][:class])
12
+ options[:html][:class] << 'form-horizontal' if options[:html][:class].empty?
13
+ options[:html][:class] << 'save-error' if Array(object).last.errors.of_kind?(:base, :changed)
12
14
  options[:builder] ||= ::AbAdmin::Views::FormBuilder
13
15
  options[:html]['data-id'] = record.id
14
16
  if controller_name == 'manager' && resource_class == Array(object).last.class
@@ -21,11 +23,11 @@ module AbAdmin
21
23
  end
22
24
  end
23
25
 
24
- def editable_bool(item, attr, label: nil)
26
+ def editable_bool(item, attr, label: nil, wrapper_class: nil)
25
27
  url = "/admin/#{item.class.model_name.plural}/#{item.id}.json"
26
28
  html = check_box_tag("#{item.class.model_name.singular}[#{attr}]", '1', item.send(attr), class: 'js-auto-submit-checkbox', data: {url: url})
27
29
  html = content_tag(:label, "#{label}&nbsp;#{html}".html_safe) if label
28
- content_tag :div, html, class: 'auto-submit-checkbox-wrap white-space-nowrap'
30
+ content_tag :div, html, class: ['auto-submit-checkbox-wrap', 'white-space-nowrap', ('tool' unless label), wrapper_class], title: attr
29
31
  end
30
32
 
31
33
  def admin_editable(item, attr, opts=nil)
@@ -78,11 +80,11 @@ module AbAdmin
78
80
  value: opts[:value] || item[attr],
79
81
  title: opts[:title] || item[attr]
80
82
  }
81
- link_to html_title, '#', class: "editable #{opts[:class]}", data: data.update(opts[:data] || {})
83
+ link_to html_title, '#', class: "editable #{opts[:class]}", placeholder: opts[:placeholder], data: data.update(opts[:data] || {})
82
84
  end
83
85
 
84
86
  def options_for_ckeditor(options = {})
85
- {width: 930, height: 200, toolbar: 'VeryEasy', namespace: ''}.update(options)
87
+ {width: 930, height: 200, namespace: ''}.update(options)
86
88
  end
87
89
 
88
90
  def admin_tree_item(item)
@@ -97,13 +99,13 @@ module AbAdmin
97
99
  def admin_layout_css
98
100
  css = []
99
101
  css << 'content_with_sidebar' if settings[:sidebar] || content_for?(:sidebar)
100
- css << 'well' if settings[:well] && current_index_view != 'tree'
101
- css << "#{current_index_view}_view"
102
+ css << 'well' if !@settings[:well].is_a?(FalseClass) && (collection_action? || %w(show history).include?(action_name)) && @settings[:current_index_view] != :tree
103
+ css << "#{settings[:current_index_view]}_view"
102
104
  css
103
105
  end
104
106
 
105
107
  def admin_title
106
- base = @breadcrumbs ? @breadcrumbs.map_val(:name).reverse : []
108
+ base = @breadcrumbs ? @breadcrumbs.map{|b| b[:name] }.reverse : []
107
109
  base << @page_title || 'Ab Admin'
108
110
  base.join(' - ')
109
111
  end
@@ -123,18 +125,27 @@ module AbAdmin
123
125
  %(<span class="badge #{css}">#{text}</span>).html_safe
124
126
  end
125
127
 
126
- def icon(name, white=false)
127
- "<i class='icon-#{name} #{'icon-white' if white}'></i> ".html_safe
128
+ def icon(name, white=false, title: nil)
129
+ title_html = %( title="#{h(title)}") if title
130
+ "<i class='icon-#{name}#{' icon-white' if white}#{' tool' if title}'#{title_html}></i> ".html_safe
131
+ end
132
+
133
+ def locale_flag(code)
134
+ (AbAdmin.locale_to_country_code[code] || code).to_s[0..1].upcase.tr('A-Z', '🇦-🇿')
128
135
  end
129
136
 
130
137
  def admin_pretty_data(object)
131
138
  case object
132
- when String, Integer, BigDecimal, Float
139
+ when Integer, BigDecimal, Float
133
140
  object
141
+ when String
142
+ object.html_safe? ? object : object.no_html.gsub("\n", '<br/>').html_safe
134
143
  when TrueClass, FalseClass
135
144
  color_bool(object)
136
- when Date, DateTime, Time, ActiveSupport::TimeWithZone
137
- I18n.l(object, format: :long)
145
+ when Date
146
+ I18n.l(object, format: AbAdmin.date_format)
147
+ when DateTime, Time, ActiveSupport::TimeWithZone
148
+ I18n.l(object, format: AbAdmin.datetime_format)
138
149
  when NilClass
139
150
  ''
140
151
  when ActiveRecord::Base
@@ -167,10 +178,6 @@ module AbAdmin
167
178
  image_tag_if(item.send(assoc).try(:url, size))
168
179
  end
169
180
 
170
- def per_page_variants
171
- AbAdmin.per_page_variants.map{|variant| [variant, max_per_page].min }.uniq
172
- end
173
-
174
181
  # input_set 'title', legend_class: 'do_sort', label_class: 'label-info' do
175
182
  def input_set(title, options={}, &block)
176
183
  options.reverse_merge!(class: "inputs well well-small clearfix #{options.delete(:legend_class) || 'do_sort'}", id: options.delete(:legend_id))
@@ -179,6 +186,11 @@ module AbAdmin
179
186
  content_tag(:div, html, options)
180
187
  end
181
188
 
189
+ def copy_btn(text, btn_text: nil, tooltip: false)
190
+ return if text.blank?
191
+ content_tag(:div, "#{icon('share')} #{btn_text}".html_safe, 'data-clipboard-text' => text, class: ['btn', 'btn-mini', 'js-copy', ('tool' if tooltip)], title: (text.no_html if tooltip))
192
+ end
193
+
182
194
  def ha(attr)
183
195
  resource_class.han(attr)
184
196
  end
@@ -187,16 +199,19 @@ module AbAdmin
187
199
  AbAdmin.site_name.is_a?(String) ? AbAdmin.site_name : AbAdmin.site_name.call
188
200
  end
189
201
 
190
- def call_method_or_proc_on(obj, symbol_or_proc, options = {})
191
- exec = options[:exec].nil? ? true : options[:exec]
192
- case symbol_or_proc
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
197
- obj.send(symbol_or_proc.to_sym)
198
- when Proc
199
- exec ? instance_exec(obj, &symbol_or_proc) : symbol_or_proc.call(obj)
202
+ def option_conditions_met?(options, object=nil)
203
+ return true unless options
204
+ condition = options[:if] || options[:unless]
205
+ return true unless condition
206
+ options[:if] ? method_or_proc_on(condition, object) : !method_or_proc_on(condition, object)
207
+ end
208
+
209
+ def method_or_proc_on(symbol_or_proc, object=nil)
210
+ return unless symbol_or_proc
211
+ if symbol_or_proc.is_a?(Symbol)
212
+ (object || self).public_send(symbol_or_proc)
213
+ else
214
+ object ? instance_exec(object, &symbol_or_proc) : instance_exec(&symbol_or_proc)
200
215
  end
201
216
  end
202
217
  end
@@ -16,7 +16,7 @@ module AbAdmin
16
16
  end
17
17
 
18
18
  def list_sort_link(attribute, options={})
19
- adapter = options[:adapter] || @search
19
+ adapter = options[:adapter] || ransack_collection
20
20
  if adapter && adapter.klass == resource_class
21
21
  sort_link(adapter, attribute, options)
22
22
  else
@@ -25,7 +25,7 @@ module AbAdmin
25
25
  end
26
26
 
27
27
  def sort_link(adapter, attribute, options={})
28
- name = options[:title] || (attribute.is_a?(Symbol) ? ha(attribute) : attribute)
28
+ name = options.delete(:title) || (attribute.is_a?(Symbol) ? ha(attribute) : attribute)
29
29
  return name unless adapter
30
30
  search_params = (params[:q] || {}).to_h.with_indifferent_access
31
31
  attr_name = (options.delete(:column) || attribute).to_s
@@ -48,7 +48,7 @@ module AbAdmin
48
48
  html_options = options.delete(:html_options) || {}
49
49
  html_options[:class] = ['sort_link', current_dir, html_options[:class]].compact.join(' ')
50
50
 
51
- options.merge!(q: search_params.merge(s: "#{attr_name} #{new_dir}"), **scope_params)
51
+ options.merge!(q: search_params.merge(s: "#{attr_name} #{new_dir}"), **collection_params)
52
52
  link_to [name, order_indicator_for(current_dir)].join(' ').html_safe, url_for(options), html_options
53
53
  end
54
54
 
@@ -62,8 +62,8 @@ module AbAdmin
62
62
  end
63
63
  end
64
64
 
65
- def scope_params
66
- params.slice(*button_scopes.map(&:first)).permit!.to_h.symbolize_keys
65
+ def collection_params
66
+ params.slice(:index_view, :view_options, *button_scopes.map(&:name)).permit!.to_h.symbolize_keys
67
67
  end
68
68
 
69
69
  def short_action_link(action, item)
@@ -80,9 +80,7 @@ module AbAdmin
80
80
  class: 'btn btn-info', title: t('admin.actions.show.link')
81
81
  when :preview
82
82
  preview_path = preview_resource_path(item)
83
- if preview_path
84
- link_to icon('eye-open', true), preview_path, class: 'btn btn-inverse', title: t('admin.actions.preview.link'), target: '_blank'
85
- end
83
+ link_to(icon('eye-open', true), preview_path, class: 'btn btn-inverse', title: t('admin.actions.preview.link'), target: '_blank') if preview_path
86
84
  when :history
87
85
  item_link_to_can? :history, item, icon('book', true), history_resource_path(item),
88
86
  class: 'btn btn-info', title: t('admin.actions.history.link')
@@ -111,9 +109,8 @@ module AbAdmin
111
109
  when :show
112
110
  link_to_can? :show, t('admin.actions.show.link'), resource_path, class: 'btn btn-info'
113
111
  when :preview
114
- if path = preview_resource_path(resource)
115
- link_to t('admin.actions.preview.link'), path, class: 'btn btn-inverse', title: t('admin.actions.preview.link'), target: '_blank'
116
- end
112
+ preview_path = preview_resource_path(resource)
113
+ link_to(t('admin.actions.preview.link'), preview_path, class: 'btn btn-inverse', title: t('admin.actions.preview.link'), target: '_blank') if preview_path
117
114
  when :history
118
115
  link_to_can? :history, t('admin.actions.history.link'), history_resource_path, class: 'btn btn-info'
119
116
  when AbAdmin::Config::ActionItem
@@ -129,8 +126,14 @@ module AbAdmin
129
126
  end
130
127
  end
131
128
 
129
+ def preview_resource_path(item)
130
+ return unless controller_name == 'manager' && manager.preview_path && option_conditions_met?(manager.preview_path[:options], item)
131
+ manager.preview_path[:value].is_a?(Symbol) ? public_send(manager.preview_path[:value], item) : instance_exec(item, &manager.preview_path[:value])
132
+ end
133
+
132
134
  def link_to_can?(act, *args, &block)
133
- item_link_to_can?(act, get_subject, *args, &block)
135
+ subject = params[:id] ? resource : resource_class
136
+ item_link_to_can?(act, subject, *args, &block)
134
137
  end
135
138
 
136
139
  def item_link_to_can?(act, item, *args, &block)
@@ -167,8 +170,7 @@ module AbAdmin
167
170
  if total_entries.zero?
168
171
  t('will_paginate.pagination_info_empty')
169
172
  else
170
- per_page = (params[:per_page] || resource_class.per_page).to_i
171
- t('will_paginate.pagination_info', from: offset + 1, to: [offset + per_page, total_entries].min, count: total_entries).html_safe
173
+ t('will_paginate.pagination_info', from: offset + 1, to: [offset + settings[:per_page], total_entries].min, count: total_entries).html_safe
172
174
  end
173
175
  end
174
176
 
@@ -192,7 +194,7 @@ module AbAdmin
192
194
  end
193
195
 
194
196
  def admin_comments_button(item)
195
- title = [icon('comment', true), item.admin_comments_count_non_zero].compact.join(' ').html_safe
197
+ title = [icon('comment', true), (item.admin_comments_count unless item.admin_comments_count.zero?)].compact.join(' ').html_safe
196
198
  link_to title, admin_admin_comments_path(resource_type: item.class.name, resource_id: item.id), remote: true,
197
199
  class: 'btn btn-info list_admin_comments_link'
198
200
  end
@@ -208,7 +210,7 @@ module AbAdmin
208
210
  def batch_action_item(item)
209
211
  if settings[:batch]
210
212
  content_tag :td do
211
- check_box_tag 'by_ids[]', item.id, false, id: "batch_action_item_#{item.id}", class: 'batch_check'
213
+ check_box_tag 'q[id_in][]', item.id, false, id: "batch_action_item_#{item.id}", class: 'batch_check'
212
214
  end
213
215
  end
214
216
  end
@@ -93,21 +93,23 @@ module AbAdmin
93
93
  return if @disable_all
94
94
  model = @object.class.reflect_on_association(assoc).klass
95
95
  title = [@template.icon('plus', true), I18n.t('admin.add'), options[:title] || model.model_name.human].join(' ').html_safe
96
- link_to_add title, assoc, class: "btn btn-primary #{options[:class]}"
96
+ options[:class] = "btn btn-primary #{options[:class]}"
97
+ link_to_add title, assoc, options
97
98
  end
98
99
 
99
- def link_to_remove_assoc
100
+ def link_to_remove_assoc(options={})
100
101
  return if @disable_all
101
- link_to_remove @template.icon('trash', true) + I18n.t('admin.delete'), class: 'btn btn-danger btn-mini pull-right'
102
+ options[:class] ||= 'btn btn-danger btn-mini pull-right'
103
+ link_to_remove @template.icon('trash', true) + I18n.t('admin.delete'), options
102
104
  end
103
105
 
104
106
  def locale_tabs(options={}, &block)
105
107
  locale_html = {}
106
- options[:locales] ||= Globalize.available_locales
108
+ options[:locales] ||= AbAdmin.translated_locales
107
109
  options[:locales].each do |l|
108
110
  locale_html[l] = template.capture { block.call(l) }
109
111
  end
110
- template.render 'admin/shared/locale_tabs', locale_html: locale_html, locales: options[:locales]
112
+ template.render 'admin/shared/locale_tabs', locale_html: locale_html, locales: options[:locales], tab_nav: options[:tab_nav]
111
113
  end
112
114
 
113
115
  def save_buttons
@@ -1,15 +1,6 @@
1
1
  module AbAdmin
2
2
  module Views
3
3
  module Helpers
4
-
5
- def admin?
6
- user_signed_in? && current_user.admin?
7
- end
8
-
9
- def moderator?
10
- user_signed_in? && current_user.moderator?
11
- end
12
-
13
4
  def as_html(text)
14
5
  return ''.html_safe if text.nil?
15
6
  Nokogiri::HTML.fragment(text).to_html.html_safe
@@ -3,11 +3,7 @@ module AbAdmin
3
3
  module Inputs
4
4
  class CkeditorInput < ::SimpleForm::Inputs::Base
5
5
  def input(wrapper_options=nil)
6
- unless @builder.template.instance_variable_get(:@ckeditor_init)
7
- @builder.template.concat @builder.template.javascript_include_tag('/javascripts/ckeditor/init')
8
- @builder.template.instance_variable_set(:@ckeditor_init, true)
9
- end
10
- input_html_options.reverse_merge!({width: 800, height: 200, toolbar: 'Easy'})
6
+ input_html_options.reverse_merge!({width: 800, height: 200, data: {cdn_url: Ckeditor.cdn_url}})
11
7
  @builder.cktext_area(attribute_name, input_html_options)
12
8
  end
13
9
  end
@@ -1,9 +1,6 @@
1
1
  module AbAdmin
2
2
  module Views
3
3
  module ManagerHelpers
4
-
5
- INDEX_VIEW_ICONS = {table: 'list', tree: 'move', grid: 'th', chart: 'signal'}
6
-
7
4
  def table_builder
8
5
  manager.table ||= ::AbAdmin::Config::Table.default_for_model(resource_class)
9
6
  end
@@ -20,6 +17,14 @@ module AbAdmin
20
17
  manager.chart ||= ::AbAdmin::Config::Chart.default_for_model(resource_class)
21
18
  end
22
19
 
20
+ def stats_builder
21
+ manager.stats ||= ::AbAdmin::Config::Stats.default_for_model(resource_class)
22
+ end
23
+
24
+ def map_builder
25
+ manager.map ||= ::AbAdmin::Config::Map.default_for_model(resource_class)
26
+ end
27
+
23
28
  def modal_form_builder
24
29
  manager.modal_form ||= ::AbAdmin::Config::ModalForm.default_for_model(resource_class, skip: [:id, :created_at, :updated_at, :lft, :rgt, :depth])
25
30
  end
@@ -38,7 +43,7 @@ module AbAdmin
38
43
  elsif field.options[:image]
39
44
  item_image_link(item, assoc: field.name)
40
45
  else
41
- admin_pretty_data call_method_or_proc_on(item, field.data)
46
+ admin_pretty_data method_or_proc_on(field.data, item)
42
47
  end
43
48
  end
44
49
 
@@ -52,10 +57,14 @@ module AbAdmin
52
57
  end
53
58
  end
54
59
 
60
+ INDEX_VIEW_ICONS = {table: 'list', tree: 'move', grid: 'th', chart: 'signal', map: 'map-marker', stats: 'eye-open'}
61
+ INDEX_VIEW_SYMBOLS = {pie_chart: '◔'}
55
62
  def index_view_link(index_view)
56
- options = {class: "btn #{('active' if current_index_view == index_view)}", title: t("admin.index_view.#{index_view}", default: index_view.to_s)}
63
+ options = {class: ['btn', 'tool', 'tool-bottom', ('active' if settings[:current_index_view] == index_view)], title: t("admin.index_view.#{index_view}", default: index_view.to_s)}
57
64
  url = url_for({index_view: index_view, q: params[:q]}.reject_blank)
58
- link_to icon(INDEX_VIEW_ICONS[index_view.to_sym]), url, options
65
+ title = INDEX_VIEW_ICONS[index_view.to_sym] ? icon(INDEX_VIEW_ICONS[index_view.to_sym]) : (INDEX_VIEW_SYMBOLS[index_view.to_sym] || index_view.to_s)
66
+ options[:class] << 'btn-symbol' if INDEX_VIEW_SYMBOLS[index_view.to_sym]
67
+ link_to title, url, options
59
68
  end
60
69
  end
61
70
  end