datagrid 0.9.3 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Readme.markdown +6 -4
- data/VERSION +1 -1
- data/app/assets/stylesheets/datagrid.css.sass +132 -0
- data/app/views/datagrid/_form.html.erb +5 -2
- data/app/views/datagrid/_order_for.html.erb +2 -2
- data/app/views/datagrid/_table.html.erb +1 -1
- data/datagrid.gemspec +10 -3
- data/lib/datagrid.rb +1 -0
- data/lib/datagrid/column_names_attribute.rb +38 -7
- data/lib/datagrid/columns.rb +38 -4
- data/lib/datagrid/columns/column.rb +29 -1
- data/lib/datagrid/drivers/abstract_driver.rb +8 -0
- data/lib/datagrid/drivers/active_record.rb +29 -1
- data/lib/datagrid/drivers/array.rb +14 -2
- data/lib/datagrid/drivers/mongo_mapper.rb +8 -0
- data/lib/datagrid/drivers/mongoid.rb +9 -1
- data/lib/datagrid/filters.rb +24 -6
- data/lib/datagrid/filters/base_filter.rb +42 -14
- data/lib/datagrid/filters/boolean_enum_filter.rb +1 -1
- data/lib/datagrid/filters/dynamic_filter.rb +57 -0
- data/lib/datagrid/filters/enum_filter.rb +4 -21
- data/lib/datagrid/filters/select_options.rb +26 -0
- data/lib/datagrid/form_builder.rb +41 -8
- data/lib/datagrid/helper.rb +2 -1
- data/lib/datagrid/i18n.rb +0 -0
- data/lib/datagrid/locale/en.yml +28 -0
- data/lib/datagrid/ordering.rb +33 -19
- data/lib/datagrid/utils.rb +8 -9
- data/spec/datagrid/column_names_attribute_spec.rb +44 -1
- data/spec/datagrid/columns_spec.rb +16 -0
- data/spec/datagrid/filters/dynamic_filter_spec.rb +37 -0
- data/spec/datagrid/filters/integer_filter_spec.rb +18 -0
- data/spec/datagrid/filters/string_filter_spec.rb +25 -0
- data/spec/datagrid/filters_spec.rb +15 -1
- data/spec/datagrid/form_builder_spec.rb +83 -0
- data/spec/datagrid/helper_spec.rb +1 -0
- data/spec/datagrid/ordering_spec.rb +41 -1
- data/spec/datagrid/utils_spec.rb +7 -2
- metadata +11 -4
@@ -66,6 +66,14 @@ module Datagrid
|
|
66
66
|
raise NotImplementedError
|
67
67
|
end
|
68
68
|
|
69
|
+
def contains(scope, field, value)
|
70
|
+
raise NotImplementedError
|
71
|
+
end
|
72
|
+
|
73
|
+
def column_names(scope)
|
74
|
+
raise NotImplementedError
|
75
|
+
end
|
76
|
+
|
69
77
|
protected
|
70
78
|
def timestamp_class?(klass)
|
71
79
|
TIMESTAMP_CLASSES.include?(klass)
|
@@ -40,6 +40,10 @@ module Datagrid
|
|
40
40
|
scope.reorder(order).reverse_order
|
41
41
|
end
|
42
42
|
|
43
|
+
def reverse_order(scope)
|
44
|
+
scope.reverse_order
|
45
|
+
end
|
46
|
+
|
43
47
|
def default_order(scope, column_name)
|
44
48
|
has_column?(scope, column_name) ? [scope.table_name, column_name].join(".") : nil
|
45
49
|
end
|
@@ -58,8 +62,22 @@ module Datagrid
|
|
58
62
|
false
|
59
63
|
end
|
60
64
|
|
65
|
+
def column_names(scope)
|
66
|
+
scope.column_names
|
67
|
+
end
|
68
|
+
|
61
69
|
def is_timestamp?(scope, field)
|
62
|
-
|
70
|
+
column_type(scope, field) == :datetime
|
71
|
+
end
|
72
|
+
|
73
|
+
def contains(scope, field, value)
|
74
|
+
if column_type(scope, field) == :string
|
75
|
+
field = prefix_table_name(scope, field)
|
76
|
+
scope.where("#{field} #{contains_predicate} ?", "%#{value}%")
|
77
|
+
else
|
78
|
+
# dont support contains operation by non-varchar column now
|
79
|
+
scope.where("1=0")
|
80
|
+
end
|
63
81
|
end
|
64
82
|
|
65
83
|
protected
|
@@ -67,6 +85,16 @@ module Datagrid
|
|
67
85
|
def prefix_table_name(scope, field)
|
68
86
|
has_column?(scope, field) ? [scope.table_name, field].join(".") : field
|
69
87
|
end
|
88
|
+
|
89
|
+
def contains_predicate
|
90
|
+
defined?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) &&
|
91
|
+
::ActiveRecord::Base.connection.is_a?(::ActiveRecord::ConnectionAdapters::PostgreSQLAdapter) ?
|
92
|
+
'ilike' : 'like'
|
93
|
+
end
|
94
|
+
|
95
|
+
def column_type(scope, field)
|
96
|
+
has_column?(scope, field) ? scope.columns_hash[field.to_s].type : nil
|
97
|
+
end
|
70
98
|
end
|
71
99
|
end
|
72
100
|
end
|
@@ -34,13 +34,15 @@ module Datagrid
|
|
34
34
|
|
35
35
|
def greater_equal(scope, field, value)
|
36
36
|
scope.select do |object|
|
37
|
-
object.send(field)
|
37
|
+
compare_value = object.send(field)
|
38
|
+
compare_value.respond_to?(:>=) && compare_value >= value
|
38
39
|
end
|
39
40
|
end
|
40
41
|
|
41
42
|
def less_equal(scope, field, value)
|
42
43
|
scope.select do |object|
|
43
|
-
object.send(field)
|
44
|
+
compare_value = object.send(field)
|
45
|
+
compare_value.respond_to?(:<=) && compare_value <= value
|
44
46
|
end
|
45
47
|
end
|
46
48
|
|
@@ -52,6 +54,16 @@ module Datagrid
|
|
52
54
|
has_column?(scope, column_name) &&
|
53
55
|
timestamp_class?(scope.first.send(column_name).class)
|
54
56
|
end
|
57
|
+
|
58
|
+
def contains(scope, field, value)
|
59
|
+
scope.select do |object|
|
60
|
+
object.send(field).to_s.include?(value)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def column_names(scope)
|
65
|
+
[]
|
66
|
+
end
|
55
67
|
end
|
56
68
|
end
|
57
69
|
end
|
@@ -47,6 +47,14 @@ module Datagrid
|
|
47
47
|
#TODO implement the support
|
48
48
|
false
|
49
49
|
end
|
50
|
+
|
51
|
+
def contains(scope, field, value)
|
52
|
+
scope(field => Regexp.compile(Regexp.escape(value)))
|
53
|
+
end
|
54
|
+
|
55
|
+
def column_names(scope)
|
56
|
+
[] # TODO: implement support
|
57
|
+
end
|
50
58
|
end
|
51
59
|
end
|
52
60
|
end
|
@@ -43,13 +43,21 @@ module Datagrid
|
|
43
43
|
end
|
44
44
|
|
45
45
|
def has_column?(scope, column_name)
|
46
|
-
|
46
|
+
column_names(scope).include?(column_name.to_s)
|
47
47
|
end
|
48
48
|
|
49
49
|
def is_timestamp?(scope, column_name)
|
50
50
|
has_column?(scope, column_name) &&
|
51
51
|
timestamp_class?(to_scope(scope).klass.fields[column_name.to_s].type)
|
52
52
|
end
|
53
|
+
|
54
|
+
def contains(scope, field, value)
|
55
|
+
scope(field => Regexp.compile(Regexp.escape(value)))
|
56
|
+
end
|
57
|
+
|
58
|
+
def column_names(scope)
|
59
|
+
to_scope(scope).klass.fields.keys
|
60
|
+
end
|
53
61
|
end
|
54
62
|
end
|
55
63
|
end
|
data/lib/datagrid/filters.rb
CHANGED
@@ -13,6 +13,7 @@ module Datagrid
|
|
13
13
|
require "datagrid/filters/composite_filters"
|
14
14
|
require "datagrid/filters/string_filter"
|
15
15
|
require "datagrid/filters/float_filter"
|
16
|
+
require "datagrid/filters/dynamic_filter"
|
16
17
|
|
17
18
|
FILTER_TYPES = {
|
18
19
|
:date => Filters::DateFilter,
|
@@ -23,6 +24,7 @@ module Datagrid
|
|
23
24
|
:integer => Filters::IntegerFilter,
|
24
25
|
:enum => Filters::EnumFilter,
|
25
26
|
:float => Filters::FloatFilter,
|
27
|
+
:dynamic => Filters::DynamicFilter
|
26
28
|
}
|
27
29
|
|
28
30
|
def self.included(base) #:nodoc:
|
@@ -72,7 +74,7 @@ module Datagrid
|
|
72
74
|
# * <tt>:dummy</tt> - if true, this filter will not be applied automatically
|
73
75
|
# and will just be displayed in form. In case you may want to apply it manually.
|
74
76
|
#
|
75
|
-
# See: https://github.com/bogdan/datagrid/wiki/
|
77
|
+
# See: https://github.com/bogdan/datagrid/wiki/Filters for examples
|
76
78
|
def filter(name, type = :default, options = {}, &block)
|
77
79
|
if type.is_a?(Hash)
|
78
80
|
options = type
|
@@ -111,11 +113,7 @@ module Datagrid
|
|
111
113
|
end
|
112
114
|
|
113
115
|
def assets # :nodoc:
|
114
|
-
|
115
|
-
self.class.filters.each do |filter|
|
116
|
-
result = filter.apply(self, result, filter_value(filter))
|
117
|
-
end
|
118
|
-
result
|
116
|
+
apply_filters(super, self.class.filters)
|
119
117
|
end
|
120
118
|
|
121
119
|
# Returns all defined filters Array
|
@@ -128,11 +126,31 @@ module Datagrid
|
|
128
126
|
self[filter.name]
|
129
127
|
end
|
130
128
|
|
129
|
+
# Returns string representation of filter value
|
130
|
+
def filter_value_as_string(filter)
|
131
|
+
value = filter_value(filter)
|
132
|
+
value = value.is_a?(Array) ? value.join(filter.separator) : value.to_s
|
133
|
+
value.blank? ? nil : value
|
134
|
+
end
|
135
|
+
|
131
136
|
# Returns filter object with the given name
|
132
137
|
def filter_by_name(name)
|
133
138
|
self.class.filter_by_name(name)
|
134
139
|
end
|
135
140
|
|
141
|
+
# Returns assets filtered only by specified filters
|
142
|
+
# Allows partial filtering
|
143
|
+
def filter_by(*filters)
|
144
|
+
apply_filters(scope, filters.map{|f| filter_by_name(f)})
|
145
|
+
end
|
146
|
+
|
147
|
+
protected
|
148
|
+
|
149
|
+
def apply_filters(current_scope, filters)
|
150
|
+
filters.inject(current_scope) do |result, filter|
|
151
|
+
filter.apply(self, result, filter_value(filter))
|
152
|
+
end
|
153
|
+
end
|
136
154
|
end # InstanceMethods
|
137
155
|
|
138
156
|
end
|
@@ -16,14 +16,15 @@ class Datagrid::Filters::BaseFilter
|
|
16
16
|
raise NotImplementedError, "#parse(value) suppose to be overwritten"
|
17
17
|
end
|
18
18
|
|
19
|
+
|
20
|
+
def unapplicable_value?(value)
|
21
|
+
value.nil? ? !allow_nil? : value.blank? && !allow_blank?
|
22
|
+
end
|
23
|
+
|
19
24
|
def apply(grid_object, scope, value)
|
20
|
-
if value
|
21
|
-
return scope if !allow_nil?
|
22
|
-
else
|
23
|
-
return scope if value.blank? && !allow_blank?
|
24
|
-
end
|
25
|
+
return scope if unapplicable_value?(value)
|
25
26
|
|
26
|
-
result = execute(value, scope, grid_object
|
27
|
+
result = execute(value, scope, grid_object)
|
27
28
|
return scope unless result
|
28
29
|
unless grid_object.driver.match?(result)
|
29
30
|
raise Datagrid::FilteringError, "Can not apply #{name.inspect} filter: result #{result.inspect} no longer match #{grid_object.driver.class}."
|
@@ -32,14 +33,20 @@ class Datagrid::Filters::BaseFilter
|
|
32
33
|
end
|
33
34
|
|
34
35
|
def parse_values(value)
|
35
|
-
if
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
36
|
+
if multiple?
|
37
|
+
normalize_multiple_value(value).map do |v|
|
38
|
+
parse(v)
|
39
|
+
end
|
40
|
+
else
|
41
|
+
if value.is_a?(Array)
|
42
|
+
raise Datagrid::ArgumentError, "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option."
|
43
|
+
end
|
44
|
+
parse(value)
|
41
45
|
end
|
42
|
-
|
46
|
+
end
|
47
|
+
|
48
|
+
def separator
|
49
|
+
options[:multiple].is_a?(String) ? options[:multiple] : default_separator
|
43
50
|
end
|
44
51
|
|
45
52
|
def header
|
@@ -53,6 +60,11 @@ class Datagrid::Filters::BaseFilter
|
|
53
60
|
end
|
54
61
|
|
55
62
|
def multiple
|
63
|
+
Datagrid::Utils.warn_once("Filter#multiple method is deprecated. Use Filter#multiple? instead")
|
64
|
+
multiple?
|
65
|
+
end
|
66
|
+
|
67
|
+
def multiple?
|
56
68
|
self.options[:multiple]
|
57
69
|
end
|
58
70
|
|
@@ -102,7 +114,7 @@ class Datagrid::Filters::BaseFilter
|
|
102
114
|
driver.where(scope, name, value)
|
103
115
|
end
|
104
116
|
|
105
|
-
def execute(value, scope, grid_object
|
117
|
+
def execute(value, scope, grid_object)
|
106
118
|
if block.arity == 1
|
107
119
|
scope.instance_exec(value, &block)
|
108
120
|
else
|
@@ -110,5 +122,21 @@ class Datagrid::Filters::BaseFilter
|
|
110
122
|
end
|
111
123
|
end
|
112
124
|
|
125
|
+
def normalize_multiple_value(value)
|
126
|
+
case value
|
127
|
+
when String
|
128
|
+
#TODO: write tests and doc
|
129
|
+
value.split(separator)
|
130
|
+
when Array
|
131
|
+
value
|
132
|
+
else
|
133
|
+
Array.wrap(value)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
def default_separator
|
138
|
+
','
|
139
|
+
end
|
140
|
+
|
113
141
|
end
|
114
142
|
|
@@ -5,7 +5,7 @@ class Datagrid::Filters::BooleanEnumFilter < Datagrid::Filters::EnumFilter
|
|
5
5
|
|
6
6
|
def initialize(report, attribute, options = {}, &block)
|
7
7
|
options[:select] = [YES, NO].map do |key, value|
|
8
|
-
[I18n.t("datagrid.filters.eboolean.#{key.downcase}"
|
8
|
+
[I18n.t("datagrid.filters.eboolean.#{key.downcase}"), key]
|
9
9
|
end
|
10
10
|
super(report, attribute, options, &block)
|
11
11
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require "datagrid/filters/select_options"
|
2
|
+
|
3
|
+
class Datagrid::Filters::DynamicFilter < Datagrid::Filters::BaseFilter
|
4
|
+
|
5
|
+
include Datagrid::Filters::SelectOptions
|
6
|
+
|
7
|
+
def initialize(*)
|
8
|
+
super
|
9
|
+
options[:multiple] = true
|
10
|
+
options[:select] ||= default_select
|
11
|
+
end
|
12
|
+
|
13
|
+
def parse(value)
|
14
|
+
value
|
15
|
+
end
|
16
|
+
|
17
|
+
def unapplicable_value?(filter)
|
18
|
+
field, operation, value = filter
|
19
|
+
field.blank? || operation.blank? || super(value)
|
20
|
+
end
|
21
|
+
|
22
|
+
def default_filter_where(driver, scope, filter)
|
23
|
+
field, operation, value = filter
|
24
|
+
driver.to_scope(scope)
|
25
|
+
case operation
|
26
|
+
when '='
|
27
|
+
driver.where(scope, field, value)
|
28
|
+
when '=~'
|
29
|
+
driver.contains(scope, field, value)
|
30
|
+
when '>='
|
31
|
+
driver.greater_equal(scope, field, value)
|
32
|
+
when '<='
|
33
|
+
driver.less_equal(scope, field, value)
|
34
|
+
else
|
35
|
+
raise "unknown operation: #{operation.inspect}"
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def operations_select
|
40
|
+
%w(= =~ >= <=).map do |operation|
|
41
|
+
I18n.t(operation, :scope => "datagrid.filters.dynamic.operations")
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
def default_select
|
48
|
+
proc {|grid|
|
49
|
+
grid.driver.column_names(grid.scope).map do |name|
|
50
|
+
# Mongodb/Rails problem:
|
51
|
+
# '_id'.humanize returns ''
|
52
|
+
[name.gsub(/^_/, '').humanize.strip, name]
|
53
|
+
end
|
54
|
+
}
|
55
|
+
end
|
56
|
+
|
57
|
+
end
|
@@ -1,5 +1,9 @@
|
|
1
|
+
require "datagrid/filters/select_options"
|
2
|
+
|
1
3
|
class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter
|
2
4
|
|
5
|
+
include Datagrid::Filters::SelectOptions
|
6
|
+
|
3
7
|
def initialize(*args)
|
4
8
|
super(*args)
|
5
9
|
raise Datagrid::ConfigurationError, ":select option not specified" unless options[:select]
|
@@ -10,27 +14,6 @@ class Datagrid::Filters::EnumFilter < Datagrid::Filters::BaseFilter
|
|
10
14
|
value
|
11
15
|
end
|
12
16
|
|
13
|
-
def select(object = nil)
|
14
|
-
select = self.options[:select]
|
15
|
-
if select.is_a?(Symbol)
|
16
|
-
object.send(select)
|
17
|
-
elsif select.respond_to?(:call)
|
18
|
-
Datagrid::Utils.apply_args(object, &select)
|
19
|
-
else
|
20
|
-
select
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
def include_blank
|
25
|
-
unless self.prompt
|
26
|
-
self.options.has_key?(:include_blank) ? options[:include_blank] : !multiple
|
27
|
-
end
|
28
|
-
end
|
29
|
-
|
30
|
-
def prompt
|
31
|
-
self.options.has_key?(:prompt) ? options[:prompt] : false
|
32
|
-
end
|
33
|
-
|
34
17
|
def strict
|
35
18
|
self.options[:strict]
|
36
19
|
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Datagrid::Filters::SelectOptions
|
2
|
+
|
3
|
+
def select(object = nil)
|
4
|
+
#unless object
|
5
|
+
#Datagrid::Utils.warn_once("#{self.class.name}#select without argument is deprecated")
|
6
|
+
#end
|
7
|
+
select = self.options[:select]
|
8
|
+
if select.is_a?(Symbol)
|
9
|
+
object.send(select)
|
10
|
+
elsif select.respond_to?(:call)
|
11
|
+
Datagrid::Utils.apply_args(object, &select)
|
12
|
+
else
|
13
|
+
select
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def include_blank
|
18
|
+
unless prompt
|
19
|
+
options.has_key?(:include_blank) ? options[:include_blank] : !multiple?
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def prompt
|
24
|
+
options.has_key?(:prompt) ? options[:prompt] : false
|
25
|
+
end
|
26
|
+
end
|
@@ -3,12 +3,14 @@ require "action_view"
|
|
3
3
|
module Datagrid
|
4
4
|
module FormBuilder
|
5
5
|
|
6
|
+
# Returns a form input html for the corresponding filter name
|
6
7
|
def datagrid_filter(filter_or_attribute, options = {})
|
7
8
|
filter = datagrid_get_filter(filter_or_attribute)
|
8
|
-
options =
|
9
|
+
options = add_html_classes(options, filter.name, datagrid_filter_html_class(filter))
|
9
10
|
self.send(filter.form_builder_helper_name, filter, options)
|
10
11
|
end
|
11
12
|
|
13
|
+
# Returns a form label html for the corresponding filter name
|
12
14
|
def datagrid_label(filter_or_attribute, options = {})
|
13
15
|
filter = datagrid_get_filter(filter_or_attribute)
|
14
16
|
self.label(filter.name, filter.header, options)
|
@@ -28,25 +30,52 @@ module Datagrid
|
|
28
30
|
end
|
29
31
|
|
30
32
|
def datagrid_default_filter(attribute_or_filter, options = {})
|
31
|
-
|
33
|
+
filter = datagrid_get_filter(attribute_or_filter)
|
34
|
+
value = object.filter_value_as_string(filter)
|
35
|
+
text_field filter.name, options.merge(:value => object.filter_value_as_string(filter))
|
32
36
|
end
|
33
37
|
|
34
38
|
def datagrid_enum_filter(attribute_or_filter, options = {})
|
35
39
|
filter = datagrid_get_filter(attribute_or_filter)
|
36
|
-
if !options.has_key?(:multiple) && filter.multiple
|
40
|
+
if !options.has_key?(:multiple) && filter.multiple?
|
37
41
|
options[:multiple] = true
|
38
42
|
end
|
39
|
-
select filter.name, filter.select(object) || [], {:include_blank => filter.include_blank, :prompt => filter.prompt}, options
|
43
|
+
select filter.name, filter.select(object) || [], {:include_blank => filter.include_blank, :prompt => filter.prompt, :include_hidden => false}, options
|
40
44
|
end
|
41
45
|
|
42
46
|
def datagrid_integer_filter(attribute_or_filter, options = {})
|
43
47
|
filter = datagrid_get_filter(attribute_or_filter)
|
44
|
-
if filter.multiple && self.object[filter.name].blank?
|
48
|
+
if filter.multiple? && self.object[filter.name].blank?
|
45
49
|
options[:value] = ""
|
46
50
|
end
|
47
51
|
datagrid_range_filter(:integer, filter, options)
|
48
52
|
end
|
49
53
|
|
54
|
+
def datagrid_dynamic_filter(attribute_or_filter, options = {})
|
55
|
+
filter = datagrid_get_filter(attribute_or_filter)
|
56
|
+
input_name = "#{object_name}[#{filter.name.to_s}][]"
|
57
|
+
field, operation, value = object.filter_value(filter)
|
58
|
+
options = options.merge(:name => input_name)
|
59
|
+
field_input = select(
|
60
|
+
filter.name,
|
61
|
+
filter.select(object) || [],
|
62
|
+
{
|
63
|
+
:include_blank => filter.include_blank,
|
64
|
+
:prompt => filter.prompt,
|
65
|
+
:include_hidden => false,
|
66
|
+
:selected => field
|
67
|
+
},
|
68
|
+
add_html_classes(options, "field")
|
69
|
+
)
|
70
|
+
operation_input = select(
|
71
|
+
filter.name, filter.operations_select,
|
72
|
+
{:include_blank => false, :include_hidden => false, :prompt => false, :selected => operation },
|
73
|
+
add_html_classes(options, "operation")
|
74
|
+
)
|
75
|
+
value_input = text_field(filter.name, add_html_classes(options, "value").merge(:value => value))
|
76
|
+
[field_input, operation_input, value_input].join("\n").html_safe
|
77
|
+
end
|
78
|
+
|
50
79
|
def datagrid_range_filter(type, attribute_or_filter, options = {})
|
51
80
|
filter = datagrid_get_filter(attribute_or_filter)
|
52
81
|
if filter.range?
|
@@ -58,18 +87,18 @@ module Datagrid
|
|
58
87
|
# 2 inputs: "from date" and "to date" to specify a range
|
59
88
|
[
|
60
89
|
text_field(filter.name, from_options),
|
61
|
-
I18n.t("datagrid.
|
90
|
+
I18n.t("datagrid.filters.#{type}.range_separator"),
|
62
91
|
text_field(filter.name, to_options)
|
63
92
|
].join.html_safe
|
64
93
|
else
|
65
|
-
|
94
|
+
datagrid_default_filter(filter, options)
|
66
95
|
end
|
67
96
|
end
|
68
97
|
|
69
98
|
|
70
99
|
def datagrid_range_filter_options(object, filter, type, options)
|
71
100
|
type_method_map = {:from => :first, :to => :last}
|
72
|
-
options =
|
101
|
+
options = add_html_classes(options, type)
|
73
102
|
options[:value] = filter.format(object[filter.name].try(type_method_map[type]))
|
74
103
|
# In case of datagrid ranged filter
|
75
104
|
# from and to input will have same id
|
@@ -110,6 +139,10 @@ module Datagrid
|
|
110
139
|
filter.class.to_s.demodulize.underscore
|
111
140
|
end
|
112
141
|
|
142
|
+
def add_html_classes(options, *classes)
|
143
|
+
Datagrid::Utils.add_html_classes(options, *classes)
|
144
|
+
end
|
145
|
+
|
113
146
|
class Error < StandardError
|
114
147
|
end
|
115
148
|
end
|