datagrid 0.9.3 → 1.0.0
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.
- 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
data/lib/datagrid/helper.rb
CHANGED
@@ -57,6 +57,7 @@ module Datagrid
|
|
57
57
|
|
58
58
|
# Provides access to datagrid columns data.
|
59
59
|
#
|
60
|
+
# # Suppose that <tt>grid</tt> has first_name and last_name columns
|
60
61
|
# <%= datagrid_row(grid, user) do |row| %>
|
61
62
|
# <tr>
|
62
63
|
# <td><%= row.first_name %></td>
|
@@ -73,7 +74,7 @@ module Datagrid
|
|
73
74
|
end
|
74
75
|
end
|
75
76
|
|
76
|
-
class HtmlRow
|
77
|
+
class HtmlRow #:nodoc:
|
77
78
|
def initialize(context, grid, asset)
|
78
79
|
@context = context
|
79
80
|
@grid = grid
|
File without changes
|
@@ -0,0 +1,28 @@
|
|
1
|
+
en:
|
2
|
+
datagrid:
|
3
|
+
no_results:
|
4
|
+
"——"
|
5
|
+
table:
|
6
|
+
order:
|
7
|
+
asc: "↑"
|
8
|
+
desc: "↓"
|
9
|
+
form:
|
10
|
+
search: "Search"
|
11
|
+
reset: "Reset"
|
12
|
+
filters:
|
13
|
+
integer:
|
14
|
+
range_separator:
|
15
|
+
"<span class=\"separator integer\"> - </span>"
|
16
|
+
date:
|
17
|
+
range_separator:
|
18
|
+
"<span class=\"separator date\"> - </span>"
|
19
|
+
|
20
|
+
eboolean:
|
21
|
+
"yes": "Yes"
|
22
|
+
"no": "No"
|
23
|
+
dynamic:
|
24
|
+
operations:
|
25
|
+
">=": ">="
|
26
|
+
"<=": "<="
|
27
|
+
"=": "="
|
28
|
+
"=~": "=~"
|
data/lib/datagrid/ordering.rb
CHANGED
@@ -17,10 +17,8 @@ module Datagrid
|
|
17
17
|
unless column
|
18
18
|
order_unsupported(value, "no column #{value} in #{self.class}")
|
19
19
|
end
|
20
|
-
unless column.
|
21
|
-
order_unsupported(
|
22
|
-
name, "#{self.class}##{name} don't support order"
|
23
|
-
)
|
20
|
+
unless column.supports_order?
|
21
|
+
order_unsupported(column.name, "column don't support order" )
|
24
22
|
end
|
25
23
|
value
|
26
24
|
else
|
@@ -49,25 +47,41 @@ module Datagrid
|
|
49
47
|
module InstanceMethods
|
50
48
|
|
51
49
|
def assets # :nodoc:
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
50
|
+
apply_order(super)
|
51
|
+
end
|
52
|
+
|
53
|
+
# Returns a column definition that is currently used to order assets
|
54
|
+
#
|
55
|
+
# class MyGrid
|
56
|
+
# scope { Model }
|
57
|
+
# column(:id)
|
58
|
+
# column(:name)
|
59
|
+
# end
|
60
|
+
# MyGrid.new(:order => "name").order_column # => #<Column name: "name", ...>
|
61
|
+
#
|
62
|
+
def order_column
|
63
|
+
column_by_name(order)
|
58
64
|
end
|
59
65
|
|
60
66
|
private
|
61
67
|
|
62
|
-
def apply_order(assets
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
apply_desc_order(assets, column.order)
|
68
|
+
def apply_order(assets)
|
69
|
+
return assets unless order
|
70
|
+
if order_column.order_by_value?
|
71
|
+
assets = assets.sort_by do |asset|
|
72
|
+
order_column.order_by_value(asset, self)
|
68
73
|
end
|
74
|
+
descending? ? assets.reverse : assets
|
69
75
|
else
|
70
|
-
|
76
|
+
if descending?
|
77
|
+
if order_column.order_desc
|
78
|
+
apply_asc_order(assets, order_column.order_desc)
|
79
|
+
else
|
80
|
+
apply_desc_order(assets, order_column.order)
|
81
|
+
end
|
82
|
+
else
|
83
|
+
apply_asc_order(assets, order_column.order)
|
84
|
+
end
|
71
85
|
end
|
72
86
|
end
|
73
87
|
|
@@ -90,7 +104,7 @@ module Datagrid
|
|
90
104
|
def reverse_order(assets)
|
91
105
|
driver.reverse_order(assets)
|
92
106
|
rescue NotImplementedError
|
93
|
-
self.class.order_unsupported("Your ORM do not support reverse order: please specify :order_desc option manually")
|
107
|
+
self.class.order_unsupported(order_column.name, "Your ORM do not support reverse order: please specify :order_desc option manually")
|
94
108
|
end
|
95
109
|
|
96
110
|
def apply_block_order(assets, order)
|
@@ -100,7 +114,7 @@ module Datagrid
|
|
100
114
|
when 1
|
101
115
|
order.call(assets)
|
102
116
|
else
|
103
|
-
self.class.order_unsupported("Order option proc can not handle more than one argument")
|
117
|
+
self.class.order_unsupported(order_column.name, "Order option proc can not handle more than one argument")
|
104
118
|
end
|
105
119
|
end
|
106
120
|
end # InstanceMethods
|
data/lib/datagrid/utils.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
|
-
module Datagrid
|
2
|
-
module Utils
|
1
|
+
module Datagrid
|
2
|
+
module Utils # :nodoc:
|
3
3
|
class << self
|
4
4
|
|
5
5
|
|
@@ -9,14 +9,13 @@ module Datagrid
|
|
9
9
|
TRUTH.include?(value)
|
10
10
|
end
|
11
11
|
|
12
|
-
def warn_once(message)
|
12
|
+
def warn_once(message, delay = 5)
|
13
13
|
@warnings ||= {}
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
end
|
14
|
+
timestamp = @warnings[message]
|
15
|
+
return false if timestamp && timestamp >= Time.now - delay
|
16
|
+
warn message
|
17
|
+
@warnings[message] = Time.now
|
18
|
+
true
|
20
19
|
end
|
21
20
|
|
22
21
|
def add_html_classes(options, *classes)
|
@@ -2,6 +2,49 @@ require "spec_helper"
|
|
2
2
|
|
3
3
|
describe Datagrid::ColumnNamesAttribute do
|
4
4
|
|
5
|
-
|
5
|
+
let(:column_names_filter_options) do
|
6
|
+
{}
|
7
|
+
end
|
8
|
+
|
9
|
+
let(:report) do
|
10
|
+
options = column_names_filter_options
|
11
|
+
test_report do
|
12
|
+
scope { Entry }
|
13
|
+
column_names_filter(options)
|
14
|
+
column(:id)
|
15
|
+
column(:name, :mandatory => true)
|
16
|
+
column(:category)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
subject { report }
|
20
|
+
|
21
|
+
|
22
|
+
let!(:entry) do
|
23
|
+
Entry.create!(:name => 'hello', :category => 'greeting')
|
24
|
+
end
|
25
|
+
|
26
|
+
it "should work" do
|
27
|
+
subject.column_names = [:id]
|
28
|
+
subject.mandatory_columns.map(&:name).should == [:name]
|
29
|
+
subject.optional_columns.map(&:name).should == [:id, :category]
|
30
|
+
subject.data.should == [["Id", "Name"], [entry.id, "hello"]]
|
31
|
+
columns_filter = subject.filter_by_name(:column_names)
|
32
|
+
columns_filter.should_not be_nil
|
33
|
+
columns_filter.select(subject).should == [["Id", :id], ["Category", :category]]
|
34
|
+
end
|
35
|
+
|
36
|
+
it "should show only mandatory columns by default" do
|
37
|
+
subject.row_for(entry).should == [ "hello" ]
|
38
|
+
subject.column_names = ["name", "category"]
|
39
|
+
subject.row_for(entry).should == ["hello", "greeting"]
|
40
|
+
end
|
41
|
+
|
42
|
+
|
43
|
+
context "when default option is passed to column_names_filter" do
|
44
|
+
let(:column_names_filter_options) do
|
45
|
+
{ :default => [:id] }
|
46
|
+
end
|
47
|
+
its(:data) { should == [["Id", "Name"], [entry.id, 'hello']] }
|
48
|
+
|
6
49
|
end
|
7
50
|
end
|
@@ -161,4 +161,20 @@ describe Datagrid::Columns do
|
|
161
161
|
report.rows.should == [["Hello World"]]
|
162
162
|
end
|
163
163
|
end
|
164
|
+
|
165
|
+
describe ".default_column_options" do
|
166
|
+
it "should pass default options to each column definition" do
|
167
|
+
report = test_report do
|
168
|
+
scope {Entry}
|
169
|
+
self.default_column_options = {:order => false}
|
170
|
+
column(:id)
|
171
|
+
column(:name, :order => "name")
|
172
|
+
end
|
173
|
+
first = Entry.create(:name => '1st')
|
174
|
+
second = Entry.create(:name => '2nd')
|
175
|
+
proc { report.attributes = {:order => :id} }.should raise_error(Datagrid::OrderUnsupported)
|
176
|
+
report.attributes = {:order => :name, :descending => true}
|
177
|
+
report.assets.should == [second, first]
|
178
|
+
end
|
179
|
+
end
|
164
180
|
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe Datagrid::Filters::DynamicFilter do
|
5
|
+
let(:report) do
|
6
|
+
test_report do
|
7
|
+
scope {Entry}
|
8
|
+
filter(:condition, :dynamic)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
it "should support = operation" do
|
13
|
+
report.condition = [:name, "=", "hello"]
|
14
|
+
report.assets.should include(Entry.create!(:name => 'hello'))
|
15
|
+
report.assets.should_not include(Entry.create!(:name => 'bye'))
|
16
|
+
end
|
17
|
+
it "should blank value" do
|
18
|
+
report.condition = [:name, "=", ""]
|
19
|
+
report.assets.should include(Entry.create!(:name => 'hello'))
|
20
|
+
end
|
21
|
+
it "should support =~ operation" do
|
22
|
+
report.condition = [:name, "=~", "ell"]
|
23
|
+
report.assets.should include(Entry.create!(:name => 'hello'))
|
24
|
+
report.assets.should_not include(Entry.create!(:name => 'bye'))
|
25
|
+
end
|
26
|
+
it "should support >= operation" do
|
27
|
+
report.condition = [:group_id, ">=", 2]
|
28
|
+
report.assets.should include(Entry.create!(:group_id => 3))
|
29
|
+
report.assets.should_not include(Entry.create!(:group_id => 1))
|
30
|
+
end
|
31
|
+
it "should support <= operation" do
|
32
|
+
report.condition = [:group_id, "<=", 2]
|
33
|
+
report.assets.should include(Entry.create!(:group_id => 1))
|
34
|
+
report.assets.should_not include(Entry.create!(:group_id => 3))
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -103,5 +103,23 @@ describe Datagrid::Filters::IntegerFilter do
|
|
103
103
|
report.assets.should include(Entry.create!(:group => Group.create!(:rating => 5)))
|
104
104
|
end
|
105
105
|
|
106
|
+
it "should support multiple values" do
|
107
|
+
report = test_report(:group_id => "1,2") do
|
108
|
+
scope {Entry}
|
109
|
+
filter(:group_id, :string, :multiple => true)
|
110
|
+
end
|
111
|
+
report.assets.should include(Entry.create!( :group_id => 1))
|
112
|
+
report.assets.should include(Entry.create!( :group_id => 2))
|
113
|
+
report.assets.should_not include(Entry.create!( :group_id => 3))
|
114
|
+
end
|
115
|
+
it "should support custom separator multiple values" do
|
116
|
+
report = test_report(:group_id => "1|2") do
|
117
|
+
scope {Entry}
|
118
|
+
filter(:group_id, :string, :multiple => '|')
|
119
|
+
end
|
120
|
+
report.assets.should include(Entry.create!( :group_id => 1))
|
121
|
+
report.assets.should include(Entry.create!( :group_id => 2))
|
122
|
+
report.assets.should_not include(Entry.create!( :group_id => 3))
|
123
|
+
end
|
106
124
|
|
107
125
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
|
4
|
+
describe Datagrid::Filters::StringFilter do
|
5
|
+
|
6
|
+
it "should support multiple values" do
|
7
|
+
report = test_report(:name => "one,two") do
|
8
|
+
scope {Entry}
|
9
|
+
filter(:name, :string, :multiple => true)
|
10
|
+
end
|
11
|
+
report.assets.should include(Entry.create!( :name => "one"))
|
12
|
+
report.assets.should include(Entry.create!( :name => "two"))
|
13
|
+
report.assets.should_not include(Entry.create!( :name => "three"))
|
14
|
+
end
|
15
|
+
it "should support custom separator multiple values" do
|
16
|
+
report = test_report(:name => "one,1|two,2") do
|
17
|
+
scope {Entry}
|
18
|
+
filter(:name, :string, :multiple => '|')
|
19
|
+
end
|
20
|
+
report.assets.should include(Entry.create!( :name => "one,1"))
|
21
|
+
report.assets.should include(Entry.create!( :name => "two,2"))
|
22
|
+
report.assets.should_not include(Entry.create!( :name => "one"))
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
@@ -75,7 +75,7 @@ describe Datagrid::Filters do
|
|
75
75
|
$FILTER_PERFORMED = false
|
76
76
|
report = test_report(:name => value) do
|
77
77
|
scope {Entry}
|
78
|
-
filter(:name, options) do |
|
78
|
+
filter(:name, options) do |_|
|
79
79
|
$FILTER_PERFORMED = true
|
80
80
|
self
|
81
81
|
end
|
@@ -161,4 +161,18 @@ describe Datagrid::Filters do
|
|
161
161
|
Entry.create!(:created_at => 3.days.ago)
|
162
162
|
grid.assets.should_not be_empty
|
163
163
|
end
|
164
|
+
|
165
|
+
describe "#filter_by" do
|
166
|
+
it "should allow partial filtering" do
|
167
|
+
grid = test_report do
|
168
|
+
scope {Entry}
|
169
|
+
filter(:id)
|
170
|
+
filter(:name)
|
171
|
+
end
|
172
|
+
e = Entry.create!(:name => 'hello')
|
173
|
+
grid.attributes = {:id => -1, :name => 'hello'}
|
174
|
+
grid.assets.should be_empty
|
175
|
+
grid.filter_by(:name).should_not be_empty
|
176
|
+
end
|
177
|
+
end
|
164
178
|
end
|
@@ -245,6 +245,19 @@ describe Datagrid::FormBuilder do
|
|
245
245
|
let(:_filter) { :name }
|
246
246
|
|
247
247
|
it {should equal_to_dom('<input class="name string_filter" id="report_name" name="report[name]" size="30" type="text">')}
|
248
|
+
|
249
|
+
context "when multiple option is set" do
|
250
|
+
let(:_grid) do
|
251
|
+
test_report(:name => "one,two") do
|
252
|
+
scope {Entry}
|
253
|
+
filter(:name, :string, :multiple => true)
|
254
|
+
end
|
255
|
+
end
|
256
|
+
|
257
|
+
let(:_filter) { :name }
|
258
|
+
|
259
|
+
it {should equal_to_dom('<input class="name string_filter" id="report_name" name="report[name]" size="30" type="text" value="one,two">')}
|
260
|
+
end
|
248
261
|
end
|
249
262
|
|
250
263
|
context "with non multiple filter" do
|
@@ -332,8 +345,78 @@ describe Datagrid::FormBuilder do
|
|
332
345
|
|
333
346
|
it { should equal_to_dom(expected_html) }
|
334
347
|
end
|
348
|
+
|
349
|
+
context "with dynamic filter" do
|
350
|
+
let(:filter_options) do
|
351
|
+
{}
|
352
|
+
end
|
353
|
+
|
354
|
+
let(:_grid) do
|
355
|
+
options = filter_options
|
356
|
+
test_report do
|
357
|
+
scope {Entry}
|
358
|
+
filter(:condition, :dynamic, options)
|
359
|
+
end
|
360
|
+
end
|
361
|
+
let(:_filter) { :condition }
|
362
|
+
context "with no options" do
|
363
|
+
let(:expected_html) do
|
364
|
+
<<-HTML
|
365
|
+
<select class="condition dynamic_filter field" id="report_condition" name="report[condition][]"><option value="id">Id</option>
|
366
|
+
<option value="group_id">Group</option>
|
367
|
+
<option value="name">Name</option>
|
368
|
+
<option value="category">Category</option>
|
369
|
+
<option value="access_level">Access level</option>
|
370
|
+
<option value="pet">Pet</option>
|
371
|
+
<option value="disabled">Disabled</option>
|
372
|
+
<option value="confirmed">Confirmed</option>
|
373
|
+
<option value="shipping_date">Shipping date</option>
|
374
|
+
<option value="created_at">Created at</option>
|
375
|
+
<option value="updated_at">Updated at</option></select><select class="condition dynamic_filter operation" id="report_condition" name="report[condition][]"><option value="=">=</option>
|
376
|
+
<option value="=~">=~</option>
|
377
|
+
<option value=">=">>=</option>
|
378
|
+
<option value="<="><=</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text">
|
379
|
+
HTML
|
380
|
+
end
|
381
|
+
it {should equal_to_dom(expected_html)}
|
382
|
+
|
383
|
+
end
|
384
|
+
context "when default option passed" do
|
385
|
+
let(:filter_options) do
|
386
|
+
{:select => [:id, :name], :default => [:id, '>=', 1]}
|
387
|
+
end
|
388
|
+
let(:expected_html) do
|
389
|
+
<<-HTML
|
390
|
+
<select class="condition dynamic_filter field" id="report_condition" name="report[condition][]"><option value="id" selected>id</option>
|
391
|
+
<option value="name">name</option></select><select class="condition dynamic_filter operation" id="report_condition" name="report[condition][]"><option value="=">=</option>
|
392
|
+
<option value="=~">=~</option>
|
393
|
+
<option value=">=" selected>>=</option>
|
394
|
+
<option value="<="><=</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text" value="1">
|
395
|
+
HTML
|
396
|
+
end
|
397
|
+
it {should equal_to_dom(expected_html)}
|
398
|
+
|
399
|
+
end
|
400
|
+
context "when select option passed" do
|
401
|
+
let(:filter_options) do
|
402
|
+
{:select => [:id, :name]}
|
403
|
+
end
|
404
|
+
let(:expected_html) do
|
405
|
+
<<-HTML
|
406
|
+
<select class="condition dynamic_filter field" id="report_condition" name="report[condition][]"><option value="id">id</option>
|
407
|
+
<option value="name">name</option></select><select class="condition dynamic_filter operation" id="report_condition" name="report[condition][]"><option value="=">=</option>
|
408
|
+
<option value="=~">=~</option>
|
409
|
+
<option value=">=">>=</option>
|
410
|
+
<option value="<="><=</option></select><input class="condition dynamic_filter value" id="report_condition" name="report[condition][]" size="30" type="text">
|
411
|
+
HTML
|
412
|
+
end
|
413
|
+
it {should equal_to_dom(expected_html)}
|
414
|
+
|
415
|
+
end
|
416
|
+
end
|
335
417
|
end
|
336
418
|
|
419
|
+
|
337
420
|
describe ".datagrid_label" do
|
338
421
|
let(:_grid) do
|
339
422
|
test_report do
|