ab_admin 0.2.1 → 0.2.2

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.
@@ -82,5 +82,7 @@
82
82
  color: #999;
83
83
  font-size: 18px;
84
84
  }
85
-
85
+ &.error .help-inline {
86
+ color: #b94a48;
87
+ }
86
88
  }
@@ -2,7 +2,7 @@ table.table.table-striped.index_table#list
2
2
  thead
3
3
  tr.pjax_links
4
4
  = batch_action_toggle
5
- th Id
5
+ th= sort_link(@search, :id)
6
6
  - resource_class.content_columns.map(&:name).without('updated_at').each do |col|
7
7
  th= sort_link(@search, col)
8
8
  th=t 'admin.table.actions'
@@ -1,4 +1,5 @@
1
1
  = content_tag :div, :id => element_id, :class => css_class, :data => container_data do
2
+ = error
2
3
  .fileupload-drop-area
3
4
  span= t('admin.fileupload.drop_here')
4
5
  .fileupload-list.clearfix= render :partial => "admin/fileupload/#{asset_render_template}", :collection => assets
@@ -101,7 +101,7 @@ ru:
101
101
  button: "Выберите файл"
102
102
  buttons: "Выберите файлы"
103
103
  delete: "Удалить файл"
104
- drop_here: "Перетащите файлы сюда"
104
+ drop_here: "или бросьте файл(ы) сюда"
105
105
  main_image: "Сделать главным"
106
106
  max_size: "Макс разм."
107
107
  crop: "Обрезать"
@@ -3,7 +3,7 @@ Given /^(\d+) products? exists$/ do |n|
3
3
  end
4
4
 
5
5
  When /^I check (\d+) products in the list$/ do |n|
6
- Product.first(n.to_i).pluck(:id).each do |p_id|
6
+ Product.limit(n.to_i).pluck(:id).each do |p_id|
7
7
  check("batch_action_item_#{p_id}")
8
8
  end
9
9
  end
data/lib/ab_admin.rb CHANGED
@@ -49,6 +49,7 @@ module AbAdmin
49
49
  autoload :Utilities, 'ab_admin/concerns/utilities'
50
50
  autoload :Headerable, 'ab_admin/concerns/headerable'
51
51
  autoload :NestedSet, 'ab_admin/concerns/nested_set'
52
+ autoload :Validations, 'ab_admin/concerns/validations'
52
53
  end
53
54
 
54
55
  module Controllers
@@ -59,7 +60,6 @@ module AbAdmin
59
60
  end
60
61
 
61
62
  module Mailers
62
- autoload :DevelopmentMailInterceptor, 'ab_admin/mailers/development_mail_interceptor'
63
63
  autoload :Helpers, 'ab_admin/mailers/helpers'
64
64
  autoload :MailAttachHelper, 'ab_admin/mailers/mail_attach_helper'
65
65
  end
@@ -91,6 +91,7 @@ module AbAdmin
91
91
  autoload :TreeSelectInput, 'ab_admin/views/inputs/tree_select_input'
92
92
  autoload :AssociationInput, 'ab_admin/views/inputs/association_input'
93
93
  autoload :DateTimeInput, 'ab_admin/views/inputs/date_time_input'
94
+ autoload :TokenInput, 'ab_admin/views/inputs/token_input'
94
95
  end
95
96
  end
96
97
 
@@ -13,6 +13,33 @@ module AbAdmin
13
13
  self.batch_actions = [:destroy]
14
14
  end
15
15
 
16
+ module ClassMethods
17
+ def for_input_token(r, attr='name_ru')
18
+ {:id => r.id, :text => r[attr]}
19
+ end
20
+ end
21
+
22
+ def for_input_token
23
+ {:id => self.id, :text => self.name}
24
+ end
25
+
26
+ def token_data(method, options={})
27
+ assoc = self.class.reflect_on_association(method)
28
+ records = self.send(method)
29
+ data = Array(records).map(&:for_input_token)
30
+ data = {
31
+ :pre => data.to_json,
32
+ :class => assoc.klass.name,
33
+ :multi => assoc.collection?,
34
+ :c => options.delete(:c)
35
+ }
36
+ if options[:geo_order]
37
+ singular = self.class.model_name.singular
38
+ data[:c] ||= {:with => {:lat => "#{singular}_lat", :lon => "#{singular}_lon"}}.to_json
39
+ end
40
+ options.reverse_deep_merge!(:class => 'fancy_select', :data => data)
41
+ end
42
+
16
43
  def next_prev_by_url(scope, url, prev=false)
17
44
  predicates = {'>' => '<', '<' => '>', 'desc' => 'asc', 'asc' => 'desc'}
18
45
  query = Rack::Utils.parse_nested_query(URI.parse(url).query).symbolize_keys
@@ -0,0 +1,24 @@
1
+ module AbAdmin
2
+ module Concerns
3
+ module Validations
4
+ class UniqTranslationValidator < ActiveModel::EachValidator
5
+ def validate_each(record, attribute, value)
6
+ ::I18n.available_locales.each do |l|
7
+ next if record.read_attribute(attribute, :locale => l).blank?
8
+ records_scope = record.class.const_get(:Translation).where("#{record.class.model_name.foreign_key} != #{record.id || 0}")
9
+ same = records_scope.where(:name => record.read_attribute(attribute, :locale => l), :locale => l.to_s).exists?
10
+ record.errors.add("#{attribute}_#{l}", :taken) if same
11
+ end
12
+ end
13
+ end
14
+
15
+ class AssetValidator < ActiveModel::EachValidator
16
+ def validate_each(record, attribute, value)
17
+ if Array(record.fileupload_asset(attribute)).all?{|a| a.new_record? }
18
+ record.errors.add(attribute, :blank)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -22,33 +22,19 @@ class Array
22
22
  inject(:+) / size
23
23
  end
24
24
 
25
- def zip_all
26
- self[0].zip *self[1..-1]
27
- end
28
-
29
- def safe_sd
30
- begin
31
- self.to_scale.sd
32
- rescue
33
- 0.0
34
- end
35
- end
36
-
37
- def pearson(b)
38
- return 0 if self.size != b.size || !Object.const_defined?("Statsample")
39
- Statsample::Bivariate.pearson(self.to_scale, b.to_scale)
40
- end
41
-
42
- def pluck!(method, *args)
43
- each_index { |x| self[x] = self[x].send method, *args }
44
- end
45
-
46
- alias invoke! pluck!
25
+ #def zip_all
26
+ # self[0].zip *self[1..-1]
27
+ #end
28
+ #
29
+ #def pluck!(method, *args)
30
+ # each_index { |x| self[x] = self[x].send method, *args }
31
+ #end
32
+ #
33
+ #alias invoke! pluck!
47
34
 
48
35
  def without(*values)
49
36
  copy = self.dup
50
- values.flatten.each { |value| copy.delete(value) }
51
- copy
37
+ copy.without!(*values)
52
38
  end
53
39
 
54
40
  def without!(*values)
@@ -80,11 +66,11 @@ class Array
80
66
 
81
67
  end
82
68
 
83
- module Enumerable
84
- def pluck(method, *args)
85
- map { |x| x.send method, *args }
86
- end
87
-
88
- alias invoke pluck
89
- end
69
+ #module Enumerable
70
+ # def pluck(method, *args)
71
+ # map { |x| x.send method, *args }
72
+ # end
73
+ #
74
+ # alias invoke pluck
75
+ #end
90
76
 
@@ -2,6 +2,10 @@
2
2
  class String
3
3
  #LUCENE_ESCAPE_REGEX = /(\+|-|&&|\|\||!|\(|\)|{|}|\[|\]|`|"|~|\?|:|\\)/
4
4
  LUCENE_ESCAPE_REGEX = /(\+|-|&&|\|\||!|\(|\)|{|}|\[|\]|`|"|~|\?|:|\\|\s)/
5
+ KEYBOARDS = {
6
+ :en => %{qwertyuiop[]asdfghjkl;'zxcvbnm,./},
7
+ :ru => %{йцукенгшщзхъфывапролджэячсмитьбю/}
8
+ }
5
9
 
6
10
  def lucene_escape
7
11
  self.gsub(LUCENE_ESCAPE_REGEX, "\\\\\\1")
@@ -38,21 +42,17 @@ class String
38
42
  def tr_lang(from=nil, to=nil)
39
43
  return '' if self.blank?
40
44
 
41
- keyboard = {}
42
- keyboard[:en] = %{qwertyuiop[]asdfghjkl;'zxcvbnm,./}
43
- keyboard[:ru] = %{йцукенгшщзхъфывапролджэячсмитьбю/}
44
-
45
45
  unless from || to
46
- if keyboard[:en].index(self[0])
46
+ if KEYBOARDS[:en].index(self[0])
47
47
  from, to = :en, :ru
48
- elsif keyboard[:ru].index(self[0])
48
+ elsif KEYBOARDS[:ru].index(self[0])
49
49
  from, to = :ru, :en
50
50
  else
51
51
  from, to = :en, :ru
52
52
  end
53
53
  end
54
54
 
55
- self.tr(keyboard[from], keyboard[to])
55
+ self.tr(KEYBOARDS[from], KEYBOARDS[to])
56
56
  end
57
57
 
58
58
  def count_words
@@ -15,6 +15,7 @@ module AbAdmin
15
15
  ActiveRecord::Base.send :include, AbAdmin::Concerns::Utilities
16
16
  ActiveRecord::Base.send :include, AbAdmin::Concerns::Silencer
17
17
  ActiveRecord::Base.send :extend, AbAdmin::Concerns::Silencer
18
+ ActiveRecord::Base.send :include, AbAdmin::Concerns::Validations
18
19
  end
19
20
 
20
21
  ActiveSupport.on_load :action_mailer do
@@ -51,7 +51,7 @@ module AbAdmin
51
51
  :only => [:id, :guid, :assetable_id, :assetable_type, :user_id,
52
52
  :data_file_size, :data_content_type, :is_main, :original_name],
53
53
  :root => 'asset',
54
- :methods => [:filename, :url, :preview_url, :thumb_url, :width, :height]
54
+ :methods => [:filename, :url, :thumb_url, :width, :height]
55
55
  }.merge(options || {})
56
56
 
57
57
  super
@@ -6,7 +6,7 @@ module AbAdmin
6
6
  included do
7
7
  has_one :avatar, :as => :assetable, :dependent => :destroy, :autosave => true
8
8
 
9
- scope :moderators, where(:user_role_id => [::UserRoleType.admin.id, ::UserRoleType.moderator.id])
9
+ scope :managers, where(:user_role_id => [::UserRoleType.admin.id, ::UserRoleType.moderator.id])
10
10
  scope :active, where(:trust_state => ::UserState.active.id)
11
11
  scope :admin, includes(:avatar)
12
12
 
@@ -1,3 +1,3 @@
1
1
  module AbAdmin
2
- VERSION = '0.2.1'
2
+ VERSION = '0.2.2'
3
3
  end
@@ -14,6 +14,7 @@ module AbAdmin
14
14
  map_type :tree_select, :to => ::AbAdmin::Views::Inputs::TreeSelectInput
15
15
  map_type :association, :to => ::AbAdmin::Views::Inputs::AssociationInput
16
16
  map_type :date, :time, :datetime, :to => ::AbAdmin::Views::Inputs::DateTimeInput
17
+ map_type :token, :to => ::AbAdmin::Views::Inputs::TokenInput
17
18
 
18
19
  def input(attribute_name, options = {}, &block)
19
20
  if options[:fancy]
@@ -118,6 +119,7 @@ module AbAdmin
118
119
 
119
120
  locals = {
120
121
  element_id: element_id,
122
+ error: error(attribute_name),
121
123
  file_title: (options[:file_title] || script_options['allowedExtensions'].join(', ')),
122
124
  file_max_size: max_size,
123
125
  assets: [value].flatten.delete_if { |v| v.nil? || v.new_record? },
@@ -133,6 +135,8 @@ module AbAdmin
133
135
 
134
136
  locals[:css_class] = ['fileupload', "#{locals[:asset_render_template]}_asset_type"]
135
137
  locals[:css_class] << (script_options['multiple'] ? 'many_assets' : 'one_asset')
138
+ locals[:css_class] << 'error' if locals[:error]
139
+
136
140
 
137
141
  js_opts = [locals[:element_id], template.sort_admin_assets_path(:klass => asset_klass), locals[:multiple]].map(&:inspect).join(', ')
138
142
  locals[:js] = <<-JAVASCRIPT
@@ -0,0 +1,15 @@
1
+ module AbAdmin
2
+ module Views
3
+ module Inputs
4
+ class TokenInput < ::SimpleForm::Inputs::StringInput
5
+
6
+ def input
7
+ attr = options.delete(:assoc) || attribute_name.to_s.sub(/^token_|_id$/, '')
8
+ input_html_options.reverse_deep_merge!(object.token_data(attr.to_sym, options.extract!(:geo_order, :c)))
9
+ super
10
+ end
11
+
12
+ end
13
+ end
14
+ end
15
+ end
@@ -1,19 +1,6 @@
1
- class UserState
2
- include EnumField::DefineEnum
3
- def initialize(code)
4
- @code = code.to_sym
5
- end
1
+ class UserState < AbAdmin::Models::TypeModel
2
+ self.codes = [:pending, :active, :suspended, :deleted]
3
+ self.i18n_scope = [:admin, :user, :state]
6
4
 
7
- define_enum do |builder|
8
- builder.member :pending, :object => new('pending')
9
- builder.member :active, :object => new('active')
10
- builder.member :suspended, :object => new('suspended')
11
- builder.member :deleted, :object => new('deleted')
12
- end
13
-
14
- attr_reader :code
15
-
16
- def title
17
- I18n.t(@code, :scope => [:admin, :user, :state])
18
- end
5
+ define_enum_by_codes
19
6
  end
@@ -38,14 +38,14 @@ describe User do
38
38
  @inactive = create(:user)
39
39
  end
40
40
 
41
- it 'search for moderators' do
42
- User.moderators.should_not include(@user)
43
- User.moderators.should include(@moderator)
41
+ it 'search for managers' do
42
+ User.managers.should_not include(@user)
43
+ User.managers.should include(@moderator)
44
44
  end
45
45
 
46
46
  it 'search for active users' do
47
47
  User.active.should include(@user)
48
- User.moderators.should_not include(@inactive)
48
+ User.managers.should_not include(@inactive)
49
49
  end
50
50
  end
51
51
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: ab_admin
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.1
5
+ version: 0.2.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - Alex Leschenko
@@ -797,6 +797,7 @@ files:
797
797
  - lib/ab_admin/concerns/nested_set.rb
798
798
  - lib/ab_admin/concerns/silencer.rb
799
799
  - lib/ab_admin/concerns/utilities.rb
800
+ - lib/ab_admin/concerns/validations.rb
800
801
  - lib/ab_admin/config/base.rb
801
802
  - lib/ab_admin/config/optional_display.rb
802
803
  - lib/ab_admin/controllers/callbacks.rb
@@ -818,7 +819,6 @@ files:
818
819
  - lib/ab_admin/i18n_tools/google_translate.rb
819
820
  - lib/ab_admin/i18n_tools/model_translator.rb
820
821
  - lib/ab_admin/i18n_tools/translate_app.rb
821
- - lib/ab_admin/mailers/development_mail_interceptor.rb
822
822
  - lib/ab_admin/mailers/helpers.rb
823
823
  - lib/ab_admin/mailers/mail_attach_helper.rb
824
824
  - lib/ab_admin/menu_builder.rb
@@ -846,6 +846,7 @@ files:
846
846
  - lib/ab_admin/views/inputs/color_input.rb
847
847
  - lib/ab_admin/views/inputs/date_time_input.rb
848
848
  - lib/ab_admin/views/inputs/editor_input.rb
849
+ - lib/ab_admin/views/inputs/token_input.rb
849
850
  - lib/ab_admin/views/inputs/tree_select_input.rb
850
851
  - lib/ab_admin/views/manager_helpers.rb
851
852
  - lib/ab_admin/views/search_form_builder.rb
@@ -1848,7 +1849,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
1848
1849
  version: '0'
1849
1850
  segments:
1850
1851
  - 0
1851
- hash: -831432489170112281
1852
+ hash: -2578895605994787711
1852
1853
  none: false
1853
1854
  required_rubygems_version: !ruby/object:Gem::Requirement
1854
1855
  requirements:
@@ -1857,7 +1858,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
1857
1858
  version: '0'
1858
1859
  segments:
1859
1860
  - 0
1860
- hash: -831432489170112281
1861
+ hash: -2578895605994787711
1861
1862
  none: false
1862
1863
  requirements: []
1863
1864
  rubyforge_project:
@@ -1,11 +0,0 @@
1
- module AbAdmin
2
- module Mailers
3
- class DevelopmentMailInterceptor
4
- def self.delivering_email(message)
5
- message.subject = "[#{message.to}] #{message.subject}"
6
- message.to = 'leschenko.al@gmail.com'
7
- end
8
- end
9
- end
10
- end
11
-