ab_admin 0.2.1 → 0.2.2

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