datagrid 1.8.1 → 2.0.0.pre.alpha
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +31 -7
- data/{Readme.markdown → README.md} +46 -29
- data/app/assets/stylesheets/datagrid.css +145 -0
- data/app/views/datagrid/_enum_checkboxes.html.erb +5 -3
- data/app/views/datagrid/_form.html.erb +4 -5
- data/app/views/datagrid/_head.html.erb +26 -3
- data/app/views/datagrid/_range_filter.html.erb +5 -3
- data/app/views/datagrid/_row.html.erb +12 -1
- data/app/views/datagrid/_table.html.erb +4 -4
- data/datagrid.gemspec +8 -8
- data/lib/datagrid/active_model.rb +9 -17
- data/lib/datagrid/base.rb +39 -0
- data/lib/datagrid/column_names_attribute.rb +12 -12
- data/lib/datagrid/columns/column.rb +155 -133
- data/lib/datagrid/columns.rb +495 -282
- data/lib/datagrid/configuration.rb +23 -10
- data/lib/datagrid/core.rb +184 -150
- data/lib/datagrid/deprecated_object.rb +20 -0
- data/lib/datagrid/drivers/abstract_driver.rb +13 -25
- data/lib/datagrid/drivers/active_record.rb +24 -26
- data/lib/datagrid/drivers/array.rb +26 -17
- data/lib/datagrid/drivers/mongo_mapper.rb +15 -14
- data/lib/datagrid/drivers/mongoid.rb +16 -18
- data/lib/datagrid/drivers/sequel.rb +14 -19
- data/lib/datagrid/drivers.rb +2 -1
- data/lib/datagrid/engine.rb +11 -3
- data/lib/datagrid/filters/base_filter.rb +166 -142
- data/lib/datagrid/filters/boolean_filter.rb +19 -5
- data/lib/datagrid/filters/date_filter.rb +33 -35
- data/lib/datagrid/filters/date_time_filter.rb +24 -16
- data/lib/datagrid/filters/default_filter.rb +9 -3
- data/lib/datagrid/filters/dynamic_filter.rb +151 -105
- data/lib/datagrid/filters/enum_filter.rb +43 -19
- data/lib/datagrid/filters/extended_boolean_filter.rb +39 -27
- data/lib/datagrid/filters/float_filter.rb +16 -5
- data/lib/datagrid/filters/integer_filter.rb +21 -10
- data/lib/datagrid/filters/ranged_filter.rb +66 -45
- data/lib/datagrid/filters/select_options.rb +58 -49
- data/lib/datagrid/filters/string_filter.rb +9 -4
- data/lib/datagrid/filters.rb +234 -106
- data/lib/datagrid/form_builder.rb +116 -128
- data/lib/datagrid/generators/scaffold.rb +185 -0
- data/lib/datagrid/generators/views.rb +20 -0
- data/lib/datagrid/helper.rb +397 -22
- data/lib/datagrid/ordering.rb +81 -87
- data/lib/datagrid/rspec.rb +8 -12
- data/lib/datagrid/utils.rb +42 -38
- data/lib/datagrid/version.rb +3 -1
- data/lib/datagrid.rb +18 -28
- data/templates/base.rb.erb +33 -7
- data/templates/grid.rb.erb +1 -1
- metadata +18 -19
- data/app/assets/stylesheets/datagrid.sass +0 -134
- data/lib/datagrid/filters/composite_filters.rb +0 -49
- data/lib/datagrid/renderer.rb +0 -157
- data/lib/datagrid/scaffold.rb +0 -129
- data/lib/tasks/datagrid_tasks.rake +0 -15
- data/templates/controller.rb.erb +0 -6
- data/templates/index.html.erb +0 -5
@@ -1,184 +1,208 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
# An error raise when datagrid filter is defined incorrectly and
|
2
4
|
# causes filtering chain to be broken
|
3
|
-
|
5
|
+
module Datagrid
|
6
|
+
class FilteringError < StandardError
|
7
|
+
end
|
4
8
|
end
|
5
9
|
|
6
10
|
# @!visibility private
|
7
|
-
|
11
|
+
module Datagrid
|
12
|
+
module Filters
|
13
|
+
class BaseFilter
|
14
|
+
attr_accessor :grid_class, :options, :block, :name
|
15
|
+
|
16
|
+
def initialize(grid_class, name, **options, &block)
|
17
|
+
self.grid_class = grid_class
|
18
|
+
self.name = name.to_sym
|
19
|
+
self.options = options
|
20
|
+
self.block = block
|
21
|
+
end
|
8
22
|
|
9
|
-
|
10
|
-
|
23
|
+
def parse(value)
|
24
|
+
raise NotImplementedError, "#parse(value) suppose to be overwritten"
|
25
|
+
end
|
11
26
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
self.options = options
|
16
|
-
self.block = block || default_filter_block
|
17
|
-
end
|
27
|
+
def default_input_options
|
28
|
+
{ type: "text" }
|
29
|
+
end
|
18
30
|
|
19
|
-
|
20
|
-
|
21
|
-
|
31
|
+
def unapplicable_value?(value)
|
32
|
+
value.nil? ? !allow_nil? : value.blank? && !allow_blank?
|
33
|
+
end
|
22
34
|
|
23
|
-
|
24
|
-
|
25
|
-
end
|
35
|
+
def apply(grid_object, scope, value)
|
36
|
+
return scope if unapplicable_value?(value)
|
26
37
|
|
27
|
-
|
28
|
-
return scope if unapplicable_value?(value)
|
38
|
+
result = execute(value, scope, grid_object)
|
29
39
|
|
30
|
-
|
40
|
+
return scope unless result
|
31
41
|
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
42
|
+
result = default_filter(value, scope) if result == Datagrid::Filters::DEFAULT_FILTER_BLOCK
|
43
|
+
unless grid_object.driver.match?(result)
|
44
|
+
raise(
|
45
|
+
Datagrid::FilteringError,
|
46
|
+
"Filter #{name.inspect} unapplicable: result no longer match #{grid_object.driver.class}.",
|
47
|
+
)
|
48
|
+
end
|
39
49
|
|
40
|
-
|
41
|
-
|
50
|
+
result
|
51
|
+
end
|
42
52
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
53
|
+
def parse_values(value)
|
54
|
+
if multiple?
|
55
|
+
return nil if value.nil?
|
56
|
+
|
57
|
+
return normalize_multiple_value(value).map do |v|
|
58
|
+
parse(v)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
case value
|
63
|
+
when Array
|
64
|
+
raise Datagrid::ArgumentError,
|
65
|
+
"#{grid_class}##{name} filter can not accept Array argument. Use :multiple option."
|
66
|
+
when Range
|
67
|
+
raise Datagrid::ArgumentError,
|
68
|
+
"#{grid_class}##{name} filter can not accept Range argument. Use :range option."
|
69
|
+
else
|
70
|
+
parse(value)
|
71
|
+
end
|
48
72
|
end
|
49
|
-
elsif value.is_a?(Array)
|
50
|
-
raise Datagrid::ArgumentError, "#{grid_class}##{name} filter can not accept Array argument. Use :multiple option."
|
51
|
-
else
|
52
|
-
parse(value)
|
53
|
-
end
|
54
|
-
end
|
55
73
|
|
56
|
-
|
57
|
-
|
58
|
-
|
74
|
+
def separator
|
75
|
+
options[:multiple].is_a?(String) ? options[:multiple] : default_separator
|
76
|
+
end
|
59
77
|
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
78
|
+
def header
|
79
|
+
if (header = options[:header])
|
80
|
+
Datagrid::Utils.callable(header)
|
81
|
+
else
|
82
|
+
Datagrid::Utils.translate_from_namespace(:filters, grid_class, name)
|
83
|
+
end
|
84
|
+
end
|
67
85
|
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
86
|
+
def default(object)
|
87
|
+
default = options[:default]
|
88
|
+
if default.is_a?(Symbol)
|
89
|
+
object.send(default)
|
90
|
+
elsif default.respond_to?(:call)
|
91
|
+
Datagrid::Utils.apply_args(object, &default)
|
92
|
+
else
|
93
|
+
default
|
94
|
+
end
|
95
|
+
end
|
78
96
|
|
79
|
-
|
80
|
-
|
81
|
-
|
97
|
+
def multiple?
|
98
|
+
options[:multiple]
|
99
|
+
end
|
82
100
|
|
83
|
-
|
84
|
-
|
85
|
-
|
101
|
+
def range?
|
102
|
+
false
|
103
|
+
end
|
86
104
|
|
87
|
-
|
88
|
-
|
89
|
-
|
105
|
+
def allow_nil?
|
106
|
+
options.key?(:allow_nil) ? options[:allow_nil] : options[:allow_blank]
|
107
|
+
end
|
90
108
|
|
91
|
-
|
92
|
-
|
93
|
-
|
109
|
+
def allow_blank?
|
110
|
+
options[:allow_blank]
|
111
|
+
end
|
94
112
|
|
95
|
-
|
96
|
-
|
97
|
-
|
113
|
+
def input_options
|
114
|
+
options[:input_options] || {}
|
115
|
+
end
|
98
116
|
|
99
|
-
|
100
|
-
|
101
|
-
|
117
|
+
def label_options
|
118
|
+
options[:label_options] || {}
|
119
|
+
end
|
102
120
|
|
103
|
-
|
104
|
-
|
105
|
-
|
121
|
+
def form_builder_helper_name
|
122
|
+
self.class.form_builder_helper_name
|
123
|
+
end
|
106
124
|
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
filter.default_filter(value, scope, grid)
|
111
|
-
end
|
112
|
-
end
|
125
|
+
def self.form_builder_helper_name
|
126
|
+
:"datagrid_#{to_s.demodulize.underscore}"
|
127
|
+
end
|
113
128
|
|
114
|
-
|
115
|
-
|
116
|
-
|
129
|
+
def supports_range?
|
130
|
+
self.class.ancestors.include?(::Datagrid::Filters::RangedFilter)
|
131
|
+
end
|
117
132
|
|
118
|
-
|
119
|
-
|
120
|
-
|
133
|
+
def format(value)
|
134
|
+
value&.to_s
|
135
|
+
end
|
121
136
|
|
122
|
-
|
123
|
-
|
124
|
-
|
137
|
+
def dummy?
|
138
|
+
options[:dummy]
|
139
|
+
end
|
125
140
|
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
141
|
+
def type
|
142
|
+
Datagrid::Filters::FILTER_TYPES.each do |type, klass|
|
143
|
+
return type if is_a?(klass)
|
144
|
+
end
|
145
|
+
raise "wtf is #{inspect}"
|
130
146
|
end
|
131
|
-
end
|
132
|
-
raise "wtf is #{inspect}"
|
133
|
-
end
|
134
147
|
|
135
|
-
|
136
|
-
|
137
|
-
|
148
|
+
def enabled?(grid)
|
149
|
+
::Datagrid::Utils.process_availability(grid, options[:if], options[:unless])
|
150
|
+
end
|
138
151
|
|
139
|
-
|
152
|
+
def enum_checkboxes?
|
153
|
+
false
|
154
|
+
end
|
140
155
|
|
141
|
-
|
142
|
-
|
143
|
-
|
156
|
+
def default_scope?
|
157
|
+
!block
|
158
|
+
end
|
144
159
|
|
145
|
-
|
146
|
-
if block.arity == 1
|
147
|
-
scope.instance_exec(value, &block)
|
148
|
-
else
|
149
|
-
Datagrid::Utils.apply_args(value, scope, grid_object, &block)
|
150
|
-
end
|
151
|
-
end
|
160
|
+
protected
|
152
161
|
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
value.split(separator)
|
157
|
-
when Range
|
158
|
-
[value.first, value.last]
|
159
|
-
when Array
|
160
|
-
value
|
161
|
-
else
|
162
|
-
Array.wrap(value)
|
163
|
-
end
|
164
|
-
end
|
162
|
+
def default_filter_where(scope, value)
|
163
|
+
driver.where(scope, name, value)
|
164
|
+
end
|
165
165
|
|
166
|
-
|
167
|
-
|
168
|
-
|
166
|
+
def execute(value, scope, grid_object)
|
167
|
+
if block&.arity == 1
|
168
|
+
scope.instance_exec(value, &block)
|
169
|
+
elsif block
|
170
|
+
Datagrid::Utils.apply_args(value, scope, grid_object, &block)
|
171
|
+
else
|
172
|
+
default_filter(value, scope)
|
173
|
+
end
|
174
|
+
end
|
169
175
|
|
170
|
-
|
171
|
-
|
172
|
-
|
176
|
+
def normalize_multiple_value(value)
|
177
|
+
case value
|
178
|
+
when String
|
179
|
+
value.split(separator)
|
180
|
+
when Range
|
181
|
+
[value.begin, value.end]
|
182
|
+
when Array
|
183
|
+
value
|
184
|
+
else
|
185
|
+
Array.wrap(value)
|
186
|
+
end
|
187
|
+
end
|
173
188
|
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
189
|
+
def default_separator
|
190
|
+
","
|
191
|
+
end
|
192
|
+
|
193
|
+
def driver
|
194
|
+
grid_class.driver
|
195
|
+
end
|
196
|
+
|
197
|
+
def default_filter(value, scope)
|
198
|
+
return nil if dummy?
|
199
|
+
|
200
|
+
if !driver.scope_has_column?(scope, name) && scope.respond_to?(name, true)
|
201
|
+
scope.public_send(name, value)
|
202
|
+
else
|
203
|
+
default_filter_where(scope, value)
|
204
|
+
end
|
205
|
+
end
|
180
206
|
end
|
181
207
|
end
|
182
|
-
|
183
208
|
end
|
184
|
-
|
@@ -1,9 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "datagrid/utils"
|
2
|
-
# @!visibility private
|
3
|
-
class Datagrid::Filters::BooleanFilter < Datagrid::Filters::BaseFilter
|
4
4
|
|
5
|
-
|
6
|
-
|
7
|
-
|
5
|
+
module Datagrid
|
6
|
+
module Filters
|
7
|
+
class BooleanFilter < Datagrid::Filters::BaseFilter
|
8
|
+
# @!visibility private
|
9
|
+
def initialize(grid, name, **opts)
|
10
|
+
super
|
11
|
+
options[:default] ||= false
|
12
|
+
end
|
8
13
|
|
14
|
+
def default_input_options
|
15
|
+
{ **super, type: "checkbox" }
|
16
|
+
end
|
17
|
+
|
18
|
+
def parse(value)
|
19
|
+
Datagrid::Utils.booleanize(value)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
9
23
|
end
|
@@ -1,40 +1,38 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
class Datagrid::Filters::DateFilter < Datagrid::Filters::BaseFilter
|
4
|
-
|
5
|
-
include Datagrid::Filters::RangedFilter
|
6
|
-
|
7
|
-
def apply(grid_object, scope, value)
|
8
|
-
if value.is_a?(Range)
|
9
|
-
value = value.first.beginning_of_day..value.last.end_of_day
|
10
|
-
end
|
11
|
-
super(grid_object, scope, value)
|
12
|
-
end
|
13
|
-
|
14
|
-
def parse(value)
|
15
|
-
Datagrid::Utils.parse_date(value)
|
16
|
-
end
|
1
|
+
# frozen_string_literal: true
|
17
2
|
|
3
|
+
require "datagrid/filters/ranged_filter"
|
18
4
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
5
|
+
module Datagrid
|
6
|
+
module Filters
|
7
|
+
class DateFilter < Datagrid::Filters::BaseFilter
|
8
|
+
include Datagrid::Filters::RangedFilter
|
9
|
+
|
10
|
+
def default_input_options
|
11
|
+
{ **super, type: "date" }
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(grid_object, scope, value)
|
15
|
+
value = Datagrid::Utils.format_date_as_timestamp(value) if grid_object.driver.timestamp_column?(scope, name)
|
16
|
+
super
|
17
|
+
end
|
18
|
+
|
19
|
+
def parse(value)
|
20
|
+
Datagrid::Utils.parse_date(value)
|
21
|
+
end
|
22
|
+
|
23
|
+
def format(value)
|
24
|
+
if formats.any? && value
|
25
|
+
value.strftime(formats.first)
|
26
|
+
else
|
27
|
+
super
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
protected
|
32
|
+
|
33
|
+
def formats
|
34
|
+
Array(Datagrid.configuration.date_formats)
|
35
|
+
end
|
30
36
|
end
|
31
|
-
super(scope, value)
|
32
|
-
end
|
33
|
-
|
34
|
-
protected
|
35
|
-
|
36
|
-
def formats
|
37
|
-
Array(Datagrid.configuration.date_formats)
|
38
37
|
end
|
39
38
|
end
|
40
|
-
|
@@ -1,25 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "datagrid/filters/ranged_filter"
|
2
4
|
|
3
|
-
|
5
|
+
module Datagrid
|
6
|
+
module Filters
|
7
|
+
class DateTimeFilter < Datagrid::Filters::BaseFilter
|
8
|
+
include Datagrid::Filters::RangedFilter
|
4
9
|
|
5
|
-
|
10
|
+
def default_input_options
|
11
|
+
{ **super, type: "datetime-local" }
|
12
|
+
end
|
6
13
|
|
7
|
-
|
8
|
-
|
9
|
-
|
14
|
+
def parse(value)
|
15
|
+
Datagrid::Utils.parse_datetime(value)
|
16
|
+
end
|
10
17
|
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
+
def format(value)
|
19
|
+
if formats.any? && value
|
20
|
+
value.strftime(formats.first)
|
21
|
+
else
|
22
|
+
super
|
23
|
+
end
|
24
|
+
end
|
18
25
|
|
19
|
-
|
26
|
+
protected
|
20
27
|
|
21
|
-
|
22
|
-
|
28
|
+
def formats
|
29
|
+
Array(Datagrid.configuration.datetime_formats)
|
30
|
+
end
|
31
|
+
end
|
23
32
|
end
|
24
33
|
end
|
25
|
-
|
@@ -1,5 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Datagrid
|
4
|
+
module Filters
|
5
|
+
class DefaultFilter < Datagrid::Filters::BaseFilter
|
6
|
+
def parse(value)
|
7
|
+
value
|
8
|
+
end
|
9
|
+
end
|
4
10
|
end
|
5
11
|
end
|