tabulatr 0.0.5 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog.textile +18 -0
- data/Gemfile.lock +9 -9
- data/README.textile +18 -14
- data/assets/company_logos.png +0 -0
- data/lib/tabulatr/tabulatr/finder/find_for_active_record_table.rb +72 -29
- data/lib/tabulatr/tabulatr/settings.rb +23 -16
- data/lib/tabulatr/tabulatr.rb +6 -1
- data/lib/tabulatr/version.rb +1 -1
- data/spec/dummy_app/app/controllers/products_controller.rb +4 -0
- data/spec/dummy_app/app/views/products/index_stateful.html.erb +6 -0
- data/spec/dummy_app/config/routes.rb +1 -0
- data/spec/requests/tabulatrs_spec.rb +53 -0
- data/tabulatr.gemspec +3 -4
- metadata +29 -6
data/Changelog.textile
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
h1. Changelog for tabulatr
|
2
|
+
|
3
|
+
h2. v0.0.5 (2011-03-28)
|
4
|
+
|
5
|
+
* new column option :map (defaults to true) to disable automatic mapping on the enries of the association as in
|
6
|
+
|
7
|
+
<pre>
|
8
|
+
<%= table_for @products do |t|
|
9
|
+
...
|
10
|
+
t.association :tags, :title # mapped to all tags
|
11
|
+
t.association :tags, :count, :map => false # called on the list-of-tags
|
12
|
+
end %>
|
13
|
+
</pre>
|
14
|
+
|
15
|
+
|
16
|
+
h2. v0.0.4 (2011-03-27)
|
17
|
+
|
18
|
+
* fixed the path to paging/sorting images installed by generator. Thanks to <a href="https://github.com/sdsykes" target="_blank">sdsykes</a>!
|
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
tabulatr (0.0
|
4
|
+
tabulatr (0.1.0)
|
5
5
|
id_stuffer (>= 0.0.1)
|
6
6
|
rails (~> 3.0)
|
7
7
|
whiny_hash (>= 0.0.2)
|
@@ -48,9 +48,9 @@ GEM
|
|
48
48
|
rack-test (>= 0.5.4)
|
49
49
|
selenium-webdriver (>= 0.0.27)
|
50
50
|
xpath (~> 0.1.3)
|
51
|
-
celerity (0.8.
|
52
|
-
childprocess (0.1.
|
53
|
-
ffi (~> 0.6
|
51
|
+
celerity (0.8.9)
|
52
|
+
childprocess (0.1.8)
|
53
|
+
ffi (~> 1.0.6)
|
54
54
|
columnize (0.3.2)
|
55
55
|
configuration (1.2.0)
|
56
56
|
culerity (0.2.15)
|
@@ -58,7 +58,7 @@ GEM
|
|
58
58
|
diff-lcs (1.1.2)
|
59
59
|
erubis (2.6.6)
|
60
60
|
abstract (>= 1.0.0)
|
61
|
-
ffi (0.
|
61
|
+
ffi (1.0.7)
|
62
62
|
rake (>= 0.8.7)
|
63
63
|
i18n (0.5.0)
|
64
64
|
id_stuffer (0.0.1)
|
@@ -77,7 +77,7 @@ GEM
|
|
77
77
|
nokogiri (1.4.4)
|
78
78
|
polyglot (0.3.1)
|
79
79
|
rack (1.2.2)
|
80
|
-
rack-mount (0.6.
|
80
|
+
rack-mount (0.6.14)
|
81
81
|
rack (>= 1.0.0)
|
82
82
|
rack-test (0.5.7)
|
83
83
|
rack (>= 1.0)
|
@@ -119,9 +119,9 @@ GEM
|
|
119
119
|
ruby_core_source (0.1.4)
|
120
120
|
archive-tar-minitar (>= 0.5.2)
|
121
121
|
rubyzip (0.9.4)
|
122
|
-
selenium-webdriver (0.1.
|
123
|
-
childprocess (
|
124
|
-
ffi (
|
122
|
+
selenium-webdriver (0.1.4)
|
123
|
+
childprocess (>= 0.1.7)
|
124
|
+
ffi (>= 1.0.7)
|
125
125
|
json_pure
|
126
126
|
rubyzip
|
127
127
|
sqlite3 (1.3.3)
|
data/README.textile
CHANGED
@@ -8,7 +8,7 @@ We found ourselves reinventing the wheel in every project we made, by using
|
|
8
8
|
|
9
9
|
* different paging mechanisms,
|
10
10
|
* different ways of implementing filtering/searching,
|
11
|
-
*
|
11
|
+
* different ways of implementing selecting and batch actions,
|
12
12
|
* different layouts.
|
13
13
|
|
14
14
|
We finally thought that whilst gems like Formtastic or SimpleForm provide a really cool, uniform, and concise way to implement forms, it's time for a table builder. During a project with Magento, we decided that their general tables are quite reasonable, and enterprise-proven -- so that's our starting point.
|
@@ -19,17 +19,17 @@ Every Tabulatr table consists of the following components:
|
|
19
19
|
|
20
20
|
* a wrapping form
|
21
21
|
* a 'Controls Container' containing the table-controls as
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
** the paginator,
|
23
|
+
** the batch_actions,
|
24
|
+
** the submit button,
|
25
|
+
** controls to manage selecting/checking/marking,
|
26
|
+
** an info_text
|
27
27
|
* The actual table consisting of
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
28
|
+
** A header row,
|
29
|
+
** A filter row,
|
30
|
+
** data rows,
|
31
|
+
** possibly a selecting/checking/marking column
|
32
|
+
** possibly action links/buttons
|
33
33
|
|
34
34
|
Whilst this is a strong decision, we made everything as-configurable-as-possible, there are roughly 150 options you can use to tweak almost every aspect of Tabulatr.
|
35
35
|
|
@@ -40,6 +40,7 @@ Tabulatr tries to make these common tasks as simple/transparent as possible:
|
|
40
40
|
* selecting/checking/marking
|
41
41
|
* filtering
|
42
42
|
* batch actions
|
43
|
+
* stateful index pages
|
43
44
|
|
44
45
|
h2. Example
|
45
46
|
|
@@ -60,7 +61,7 @@ In the products controllers index action we have:
|
|
60
61
|
end
|
61
62
|
</pre>
|
62
63
|
|
63
|
-
the find_for_table method is injected into ActiveRecord by Tabulatr, it retrieves all relevant data from the params hash automagically.
|
64
|
+
the <tt>find_for_table</tt> method is injected into ActiveRecord by Tabulatr, it retrieves all relevant data from the <tt>params</tt> hash automagically. If you want the the table to be stateful, i.e. remembering its sorting/filtering/selecting settings (very useful when processing a certain selection of entries), you can pass the option <tt>:stateful => session</tt> to the <tt>find_for_table</tt> call and the data will be stored. Also, a _Reset_ button will be rendered to get rid of the state.
|
64
65
|
|
65
66
|
h3. View
|
66
67
|
|
@@ -105,7 +106,9 @@ To add a select-popup with batch-actions (i.e., actions that are to be performed
|
|
105
106
|
end %>
|
106
107
|
</pre>
|
107
108
|
|
108
|
-
|
109
|
+
If you prefer individual buttons for the batch actions over a select input, give the option <tt>:batch_actions_type => :button</tt> to the <tt>table_for</tt> call.
|
110
|
+
|
111
|
+
To handle the actual batch action, we have to add a block to the <tt>find_for_table</tt> call in the controller:
|
109
112
|
|
110
113
|
<pre>
|
111
114
|
@products = Product.find_for_table(params) do |batch_actions|
|
@@ -201,6 +204,7 @@ These options are to be specified at the form_for level and change the appearanc
|
|
201
204
|
unselect_visible_label: 'Unselect visible', # Text on the unselect visible button
|
202
205
|
select_filtered_label: 'Select filtered', # Text on the select filtered button
|
203
206
|
unselect_filtered_label: 'Unselect filtered', # Text on the unselect filtered button
|
207
|
+
reset_label: 'Reset', # Text on the reset button
|
204
208
|
info_text: "Showing %1$d, total %2$d, selected %3$d, matching %4$d",
|
205
209
|
|
206
210
|
# which controls to be rendered above and below the tabel and in which order
|
@@ -313,7 +317,7 @@ We use
|
|
313
317
|
|
314
318
|
h2. Bugs
|
315
319
|
|
316
|
-
There are, definitely, roughly
|
320
|
+
There are, definitely, roughly 999 bugs in Tabulatr, although we do some testing (see <tt>spec/</tt>). So if you hunt them, please let me know using the <a href="https://github.com/provideal/tabulatr/issues">GitHub Bugtracker</a>.
|
317
321
|
|
318
322
|
h2. License
|
319
323
|
|
Binary file
|
@@ -29,8 +29,8 @@ module Tabulatr::Finder
|
|
29
29
|
# Called if SomeActveRecordSubclass::find_for_table(params) is called
|
30
30
|
#
|
31
31
|
def self.find_for_active_record_table(klaz, params, o={}, &block)
|
32
|
+
# on the first run, get the correct like db-operator, can still be ovrrridden
|
32
33
|
unless Tabulatr::SQL_OPTIONS[:like]
|
33
|
-
# get the correct like db-operator, can still be ovrrridden
|
34
34
|
case ActiveRecord::Base.connection.class.to_s
|
35
35
|
when "ActiveRecord::ConnectionAdapters::MysqlAdapter" then Tabulatr.sql_options(:like => 'LIKE')
|
36
36
|
when "ActiveRecord::ConnectionAdapters::PostgreSQLAdapter" then Tabulatr.sql_options(:like => 'ILIKE')
|
@@ -42,25 +42,88 @@ module Tabulatr::Finder
|
|
42
42
|
Tabulatr.sql_options(:like => 'LIKE')
|
43
43
|
end
|
44
44
|
end
|
45
|
+
|
45
46
|
form_options = Tabulatr.table_form_options
|
46
|
-
cname = class_to_param(klaz)
|
47
|
-
params ||= {}
|
48
47
|
opts = Tabulatr.finder_options.merge(o)
|
48
|
+
params ||= {} # just to be sure
|
49
|
+
cname = class_to_param(klaz)
|
50
|
+
pagination_name = "#{cname}#{form_options[:pagination_postfix]}"
|
51
|
+
sort_name = "#{cname}#{form_options[:sort_postfix]}"
|
52
|
+
filter_name = "#{cname}#{form_options[:filter_postfix]}"
|
53
|
+
batch_name = "#{cname}#{form_options[:batch_postfix]}"
|
54
|
+
check_name = "#{cname}#{form_options[:checked_postfix]}"
|
55
|
+
|
56
|
+
|
49
57
|
# before we do anything else, we find whether there's something to do for batch actions
|
50
58
|
checked_param = ActiveSupport::HashWithIndifferentAccess.new({:checked_ids => '', :current_page => []}).
|
51
|
-
merge(params[
|
59
|
+
merge(params[check_name] || {})
|
52
60
|
checked_ids = uncompress_id_list(checked_param[:checked_ids])
|
53
61
|
new_ids = checked_param[:current_page]
|
54
62
|
selected_ids = checked_ids + new_ids
|
55
|
-
batch_param = params[
|
63
|
+
batch_param = params[batch_name]
|
56
64
|
if batch_param.present? and block_given?
|
57
65
|
batch_param = batch_param.keys.first.to_sym if batch_param.is_a?(Hash)
|
58
66
|
yield(Invoker.new(batch_param, selected_ids))
|
59
67
|
end
|
68
|
+
|
69
|
+
# then, we obey any "select" buttons if pushed
|
70
|
+
if checked_param[:select_all]
|
71
|
+
all = klaz.find :all, :conditions => precondition, :select => :id
|
72
|
+
selected_ids = all.map { |r| r.id.to_s }
|
73
|
+
elsif checked_param[:select_none]
|
74
|
+
selected_ids = []
|
75
|
+
elsif checked_param[:select_visible]
|
76
|
+
visible_ids = uncompress_id_list(checked_param[:visible])
|
77
|
+
selected_ids = (selected_ids + visible_ids).sort.uniq
|
78
|
+
elsif checked_param[:unselect_visible]
|
79
|
+
visible_ids = uncompress_id_list(checked_param[:visible])
|
80
|
+
selected_ids = (selected_ids - visible_ids).sort.uniq
|
81
|
+
elsif checked_param[:select_filtered]
|
82
|
+
all = klaz.find :all, :conditions => conditions, :select => :id, :include => includes
|
83
|
+
selected_ids = (selected_ids + all.map { |r| r.id.to_s }).sort.uniq
|
84
|
+
elsif checked_param[:unselect_filtered]
|
85
|
+
all = klaz.find :all, :conditions => conditions, :select => :id, :include => includes
|
86
|
+
selected_ids = (selected_ids - all.map { |r| r.id.to_s }).sort.uniq
|
87
|
+
end
|
88
|
+
|
89
|
+
# at this point, we've retrieved the filter settings, the sorting setting, the pagination settings and
|
90
|
+
# the selected_ids.
|
91
|
+
filter_param = (params[filter_name] || {})
|
92
|
+
sortparam = params[sort_name]
|
93
|
+
pops = params[pagination_name] || {}
|
94
|
+
|
95
|
+
# store the state if appropriate
|
96
|
+
if opts[:stateful]
|
97
|
+
session = opts[:stateful]
|
98
|
+
sname = "#{cname}#{form_options[:state_session_postfix]}"
|
99
|
+
raise "give the session as the :stateful parameter in find_for_table" unless session.is_a?(ActionDispatch::Session::AbstractStore::SessionHash)
|
100
|
+
session[sname] ||= {}
|
101
|
+
|
102
|
+
if params["#{cname}#{form_options[:reset_state_postfix]}"]
|
103
|
+
# clicked reset button, reset all and clear session
|
104
|
+
selected_ids = []
|
105
|
+
filter_param = {}
|
106
|
+
sortparam = nil
|
107
|
+
pops = {}
|
108
|
+
session.delete sname
|
109
|
+
elsif !pops.present? && !selected_ids.present? && !sortparam.present? && !filter_param.present?
|
110
|
+
# we're supposed to retrieve the state from the session if applicable
|
111
|
+
state = session[sname]
|
112
|
+
selected_ids = state[:selected_ids] || []
|
113
|
+
filter_param = state[:filter_param] || {}
|
114
|
+
sortparam = state[:sortparam]
|
115
|
+
pops = state[:paging_param] || {}
|
116
|
+
else
|
117
|
+
# store the current settings into the session to be stateful ;)
|
118
|
+
session[sname][:selected_ids] = selected_ids
|
119
|
+
session[sname][:filter_param] = filter_param
|
120
|
+
session[sname][:sortparam] = sortparam
|
121
|
+
session[sname][:paging_param] = pops
|
122
|
+
end
|
123
|
+
end
|
60
124
|
|
61
125
|
# firstly, get the conditions from the filters
|
62
126
|
includes = []
|
63
|
-
filter_param = (params["#{cname}#{form_options[:filter_postfix]}"] || {})
|
64
127
|
precondition = opts[:precondition] || "(1=1)"
|
65
128
|
conditions = filter_param.inject([precondition.dup, []]) do |c, t|
|
66
129
|
n, v = t
|
@@ -82,7 +145,6 @@ module Tabulatr::Finder
|
|
82
145
|
conditions = [conditions.first] + conditions.last
|
83
146
|
|
84
147
|
# secondly, find the order_by stuff
|
85
|
-
sortparam = params["#{cname}#{form_options[:sort_postfix]}"]
|
86
148
|
if sortparam
|
87
149
|
if sortparam[:_resort]
|
88
150
|
order_by = sortparam[:_resort].first.first
|
@@ -108,7 +170,6 @@ module Tabulatr::Finder
|
|
108
170
|
end
|
109
171
|
|
110
172
|
# thirdly, get the pagination data
|
111
|
-
pops = params["#{cname}#{form_options[:pagination_postfix]}"] || {}
|
112
173
|
paginate_options = Tabulatr.paginate_options.merge(opts).merge(pops)
|
113
174
|
pagesize = (pops[:pagesize] || opts[:default_pagesize] || paginate_options[:pagesize]).to_f
|
114
175
|
page = paginate_options[:page].to_i
|
@@ -118,27 +179,6 @@ module Tabulatr::Finder
|
|
118
179
|
pages = (c/pagesize).ceil
|
119
180
|
page = [1, [page, pages].min].max
|
120
181
|
|
121
|
-
# then, we obey any "select" buttons if pushed
|
122
|
-
if checked_param[:select_all]
|
123
|
-
all = klaz.find :all, :conditions => precondition, :select => :id
|
124
|
-
selected_ids = all.map { |r| r.id.to_s }
|
125
|
-
elsif checked_param[:select_none]
|
126
|
-
selected_ids = []
|
127
|
-
elsif checked_param[:select_visible]
|
128
|
-
visible_ids = uncompress_id_list(checked_param[:visible])
|
129
|
-
selected_ids = (selected_ids + visible_ids).sort.uniq
|
130
|
-
elsif checked_param[:unselect_visible]
|
131
|
-
visible_ids = uncompress_id_list(checked_param[:visible])
|
132
|
-
selected_ids = (selected_ids - visible_ids).sort.uniq
|
133
|
-
elsif checked_param[:select_filtered]
|
134
|
-
all = klaz.find :all, :conditions => conditions, :select => :id, :include => includes
|
135
|
-
selected_ids = (selected_ids + all.map { |r| r.id.to_s }).sort.uniq
|
136
|
-
elsif checked_param[:unselect_filtered]
|
137
|
-
all = klaz.find :all, :conditions => conditions, :select => :id, :include => includes
|
138
|
-
selected_ids = (selected_ids - all.map { |r| r.id.to_s }).sort.uniq
|
139
|
-
end
|
140
|
-
|
141
|
-
|
142
182
|
# Now, actually find the stuff
|
143
183
|
found = klaz.find :all, :conditions => conditions,
|
144
184
|
:limit => pagesize.to_i, :offset => ((page-1)*pagesize).to_i,
|
@@ -165,6 +205,9 @@ module Tabulatr::Finder
|
|
165
205
|
:visible => visible_ids
|
166
206
|
}
|
167
207
|
end
|
208
|
+
found.define_singleton_method(fio[:stateful]) do
|
209
|
+
(opts[:stateful] ? true : false)
|
210
|
+
end
|
168
211
|
found.define_singleton_method(fio[:store_data]) do
|
169
212
|
opts[:store_data] || {}
|
170
213
|
end
|
@@ -38,6 +38,7 @@ class Tabulatr
|
|
38
38
|
:page_left_class => 'page-left', # class for the page left button
|
39
39
|
:page_right_class => 'page-right', # class for the page right button
|
40
40
|
:page_no_class => 'page-no', # class for the page no <input>
|
41
|
+
:reset_class => 'reset', # class for the reset button
|
41
42
|
:control_div_class_before => 'table-controls', # class of the upper div containing the paging and batch action controls
|
42
43
|
:control_div_class_after => 'table-controls', # class of the lower div containing the paging and batch action controls
|
43
44
|
:paginator_div_class => 'paginator', # class of the div containing the paging controls
|
@@ -63,10 +64,11 @@ class Tabulatr
|
|
63
64
|
:unselect_visible_label => 'Unselect visible', # Text on the unselect visible button
|
64
65
|
:select_filtered_label => 'Select filtered', # Text on the select filtered button
|
65
66
|
:unselect_filtered_label => 'Unselect filtered',# Text on the unselect filtered button
|
67
|
+
:reset_label => 'Reset', # Text on the reset button
|
66
68
|
:info_text => "Showing %1$d, total %2$d, selected %3$d, matching %4$d",
|
67
69
|
|
68
70
|
# which controls to be rendered above and below the tabel and in which order
|
69
|
-
:before_table_controls => [:submit, :paginator, :batch_actions, :select_controls, :info_text],
|
71
|
+
:before_table_controls => [:submit, :reset, :paginator, :batch_actions, :select_controls, :info_text],
|
70
72
|
:after_table_controls => [],
|
71
73
|
|
72
74
|
# whih selecting controls to render in which order
|
@@ -83,19 +85,20 @@ class Tabulatr
|
|
83
85
|
:sort_down_button => 'sort_arrow_down.gif',
|
84
86
|
:sort_down_button_inactive => 'sort_arrow_down_off.gif',
|
85
87
|
|
86
|
-
:make_form => true,
|
87
|
-
:table_html => false,
|
88
|
-
:row_html => false,
|
89
|
-
:header_html => false,
|
90
|
-
:filter_html => false,
|
91
|
-
:filter => true,
|
92
|
-
:paginate => true,
|
93
|
-
:sortable => true,
|
94
|
-
:selectable => true,
|
95
|
-
:
|
96
|
-
:
|
97
|
-
:
|
98
|
-
:
|
88
|
+
:make_form => true, # whether or not to wrap the whole table (incl. controls) in a form
|
89
|
+
:table_html => false, # a hash with html attributes for the table
|
90
|
+
:row_html => false, # a hash with html attributes for the normal trs
|
91
|
+
:header_html => false, # a hash with html attributes for the header trs
|
92
|
+
:filter_html => false, # a hash with html attributes for the filter trs
|
93
|
+
:filter => true, # false for no filter row at all
|
94
|
+
:paginate => true, # true to show paginator
|
95
|
+
:sortable => true, # true to allow sorting (can be specified for every sortable column)
|
96
|
+
:selectable => true, # true to render "select all", "select none" and the like
|
97
|
+
:reset => false, # true to render a reset button. Only reasonable in 'stateful' case
|
98
|
+
:action => nil, # target action of the wrapping form if applicable
|
99
|
+
:batch_actions => false, # :name => value hash of batch action stuff
|
100
|
+
:translate => false, # call t() for all 'labels' and stuff, possible values are true/:translate or :localize
|
101
|
+
:row_classes => ['odd', 'even'] # class for the trs
|
99
102
|
})
|
100
103
|
|
101
104
|
# these settings are considered constant for the whole application, can not be overridden
|
@@ -111,6 +114,8 @@ class Tabulatr
|
|
111
114
|
:associations_filter => '__association', # name of the associations in the filter hash
|
112
115
|
:method => 'post', # http method for that form if applicable
|
113
116
|
:batch_postfix => '_batch', # postfix for name of the batch action select
|
117
|
+
:state_session_postfix => '_table_state', # postfix for the state hash in the sessions
|
118
|
+
:reset_state_postfix => '_reset_state', # postfix for the name of the input to reset state
|
114
119
|
:checked_separator => ',' # symbol to separate the checked ids
|
115
120
|
})
|
116
121
|
|
@@ -160,7 +165,8 @@ class Tabulatr
|
|
160
165
|
:classname => :__classname,
|
161
166
|
:sorting => :__sorting,
|
162
167
|
:checked => :__checked,
|
163
|
-
:store_data => :__store_data
|
168
|
+
:store_data => :__store_data,
|
169
|
+
:stateful => :__stateful
|
164
170
|
})
|
165
171
|
|
166
172
|
# defaults for the find_for_table
|
@@ -168,7 +174,8 @@ class Tabulatr
|
|
168
174
|
:default_order => false,
|
169
175
|
:default_pagesize => false,
|
170
176
|
:precondition => false,
|
171
|
-
:store_data => false
|
177
|
+
:store_data => false,
|
178
|
+
:stateful => false
|
172
179
|
})
|
173
180
|
|
174
181
|
# Stupid hack
|
data/lib/tabulatr/tabulatr.rb
CHANGED
@@ -62,6 +62,7 @@ class Tabulatr
|
|
62
62
|
@sorting = @records.send(FINDER_INJECT_OPTIONS[:sorting])
|
63
63
|
@checked = @records.send(FINDER_INJECT_OPTIONS[:checked])
|
64
64
|
@store_data = @records.send(FINDER_INJECT_OPTIONS[:store_data])
|
65
|
+
@stateful = @records.send(FINDER_INJECT_OPTIONS[:stateful])
|
65
66
|
@should_translate = @table_options[:translate]
|
66
67
|
end
|
67
68
|
|
@@ -109,10 +110,14 @@ class Tabulatr
|
|
109
110
|
def render_element(element, &block)
|
110
111
|
case element
|
111
112
|
when :paginator then render_paginator if @table_options[:paginate]
|
112
|
-
when :hidden_submit then
|
113
|
+
when :hidden_submit then "IMPLEMENT ME!"
|
113
114
|
when :submit then make_tag(:input, :type => 'submit',
|
114
115
|
:class => @table_options[:submit_class],
|
115
116
|
:value => t(@table_options[:submit_label]))
|
117
|
+
when :reset then make_tag(:input, :type => 'submit',
|
118
|
+
:class => @table_options[:reset_class],
|
119
|
+
:name => "#{@classname}#{TABLE_FORM_OPTIONS[:reset_state_postfix]}",
|
120
|
+
:value => t(@table_options[:reset_label])) if @stateful
|
116
121
|
when :batch_actions then render_batch_actions if @table_options[:batch_actions]
|
117
122
|
when :select_controls then render_select_controls if @table_options[:selectable]
|
118
123
|
when :info_text
|
data/lib/tabulatr/version.rb
CHANGED
@@ -21,6 +21,10 @@ class ProductsController < ApplicationController
|
|
21
21
|
@products = Product.find_for_table(params)
|
22
22
|
end
|
23
23
|
|
24
|
+
def index_stateful
|
25
|
+
@products = Product.find_for_table(params, :stateful => session)
|
26
|
+
end
|
27
|
+
|
24
28
|
def index_select
|
25
29
|
@products = Product.find_for_table(params) do |batch_actions|
|
26
30
|
batch_actions.delete do |ids|
|
@@ -23,6 +23,8 @@ describe "Tabulatrs" do
|
|
23
23
|
FILTERS = FILTERS_WITH_LIKE = FILTERS_WITH_RANGE = tralse
|
24
24
|
# Sorting
|
25
25
|
KNOWS_HOW_TO_SORT = tralse
|
26
|
+
# Statful
|
27
|
+
SORTS_STATEFULLY = FILTERS_STATEFULLY = SELECTS_STATEFULLY = true
|
26
28
|
# selecting and batch actions
|
27
29
|
KNOWS_HOW_TO_SELECT_AND_APPLY_BATCH_ACTIONS = tralse
|
28
30
|
|
@@ -45,6 +47,7 @@ describe "Tabulatrs" do
|
|
45
47
|
].each do |n|
|
46
48
|
page.should have_button(Tabulatr::TABLE_OPTIONS[n])
|
47
49
|
end
|
50
|
+
page.should_not have_button(Tabulatr::TABLE_OPTIONS[:reset_label])
|
48
51
|
end if CONTAINS_BUTTONS
|
49
52
|
|
50
53
|
it "contains column headers" do
|
@@ -248,6 +251,56 @@ describe "Tabulatrs" do
|
|
248
251
|
end if KNOWS_HOW_TO_SORT
|
249
252
|
end
|
250
253
|
|
254
|
+
describe "statefulness" do
|
255
|
+
it "sorts statefully" do
|
256
|
+
visit index_stateful_products_path
|
257
|
+
click_button("product_sort_title_desc")
|
258
|
+
snames = names.sort
|
259
|
+
(1..10).each do |i|
|
260
|
+
page.should have_content snames[-i]
|
261
|
+
end
|
262
|
+
visit index_stateful_products_path
|
263
|
+
(1..10).each do |i|
|
264
|
+
page.should have_content snames[-i]
|
265
|
+
end
|
266
|
+
click_button("Reset")
|
267
|
+
(1..10).each do |i|
|
268
|
+
page.should have_content names[i-1]
|
269
|
+
end
|
270
|
+
end if SORTS_STATEFULLY
|
271
|
+
|
272
|
+
it "filters statefully" do
|
273
|
+
visit index_stateful_products_path
|
274
|
+
fill_in("product_filter[title]", :with => "lorem")
|
275
|
+
click_button("Apply")
|
276
|
+
visit index_stateful_products_path
|
277
|
+
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], 1, names.length, 0, 1))
|
278
|
+
click_button("Reset")
|
279
|
+
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], 10, names.length, 0, names.length))
|
280
|
+
end if FILTERS_STATEFULLY
|
281
|
+
|
282
|
+
it "selects statefully" do
|
283
|
+
visit index_stateful_products_path
|
284
|
+
n = names.length
|
285
|
+
(n/10).times do |i|
|
286
|
+
(1..3).each do |j|
|
287
|
+
check("product_checked_#{10*i+j}")
|
288
|
+
end
|
289
|
+
click_button("Apply")
|
290
|
+
tot = 3*(i+1)
|
291
|
+
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], 10, n, tot, n))
|
292
|
+
click_button('product_pagination_page_right')
|
293
|
+
end
|
294
|
+
visit index_stateful_products_path
|
295
|
+
tot = 3*(n/10)
|
296
|
+
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], names.length % 10, n, tot, n))
|
297
|
+
click_button("Reset")
|
298
|
+
page.should have_content(sprintf(Tabulatr::TABLE_OPTIONS[:info_text], 10, names.length, 0, names.length))
|
299
|
+
end if SELECTS_STATEFULLY
|
300
|
+
|
301
|
+
end
|
302
|
+
|
303
|
+
|
251
304
|
describe "Select and Batch actions" do
|
252
305
|
it "knows how to select and apply batch actions" do
|
253
306
|
visit index_select_products_path
|
data/tabulatr.gemspec
CHANGED
@@ -6,12 +6,11 @@ Gem::Specification.new do |s|
|
|
6
6
|
s.name = "tabulatr"
|
7
7
|
s.version = Tabulatr::VERSION.dup
|
8
8
|
s.platform = Gem::Platform::RUBY
|
9
|
-
s.summary = "
|
9
|
+
s.summary = "A tight DSL to build tables of ActiveRecord models with sorting, pagination, finding/filtering, selecting and batch actions."
|
10
10
|
s.email = "info@provideal.net"
|
11
11
|
s.homepage = "http://github.com/provideal/tabulatr"
|
12
|
-
s.description = "
|
13
|
-
"
|
14
|
-
"names of the columns. See the README for details."
|
12
|
+
s.description = "A tight DSL to build tables of ActiveRecord models with sorting, pagination, finding/filtering, selecting and batch actions. " +
|
13
|
+
"Tries to do for tables what formtastic and simple_form did for forms."
|
15
14
|
s.authors = ['Peter Horn', 'René Sprotte']
|
16
15
|
|
17
16
|
s.files = `git ls-files`.split("\n")
|
metadata
CHANGED
@@ -1,8 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabulatr
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
5
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 1
|
8
|
+
- 0
|
9
|
+
version: 0.1.0
|
6
10
|
platform: ruby
|
7
11
|
authors:
|
8
12
|
- Peter Horn
|
@@ -11,7 +15,7 @@ autorequire:
|
|
11
15
|
bindir: bin
|
12
16
|
cert_chain: []
|
13
17
|
|
14
|
-
date: 2011-03-
|
18
|
+
date: 2011-03-29 00:00:00 +02:00
|
15
19
|
default_executable:
|
16
20
|
dependencies:
|
17
21
|
- !ruby/object:Gem::Dependency
|
@@ -22,6 +26,9 @@ dependencies:
|
|
22
26
|
requirements:
|
23
27
|
- - ~>
|
24
28
|
- !ruby/object:Gem::Version
|
29
|
+
segments:
|
30
|
+
- 3
|
31
|
+
- 0
|
25
32
|
version: "3.0"
|
26
33
|
type: :runtime
|
27
34
|
version_requirements: *id001
|
@@ -33,6 +40,10 @@ dependencies:
|
|
33
40
|
requirements:
|
34
41
|
- - ">="
|
35
42
|
- !ruby/object:Gem::Version
|
43
|
+
segments:
|
44
|
+
- 0
|
45
|
+
- 0
|
46
|
+
- 2
|
36
47
|
version: 0.0.2
|
37
48
|
type: :runtime
|
38
49
|
version_requirements: *id002
|
@@ -44,10 +55,14 @@ dependencies:
|
|
44
55
|
requirements:
|
45
56
|
- - ">="
|
46
57
|
- !ruby/object:Gem::Version
|
58
|
+
segments:
|
59
|
+
- 0
|
60
|
+
- 0
|
61
|
+
- 1
|
47
62
|
version: 0.0.1
|
48
63
|
type: :runtime
|
49
64
|
version_requirements: *id003
|
50
|
-
description:
|
65
|
+
description: A tight DSL to build tables of ActiveRecord models with sorting, pagination, finding/filtering, selecting and batch actions. Tries to do for tables what formtastic and simple_form did for forms.
|
51
66
|
email: info@provideal.net
|
52
67
|
executables: []
|
53
68
|
|
@@ -58,11 +73,13 @@ extra_rdoc_files: []
|
|
58
73
|
files:
|
59
74
|
- .gitignore
|
60
75
|
- .rspec
|
76
|
+
- Changelog.textile
|
61
77
|
- Gemfile
|
62
78
|
- Gemfile.lock
|
63
79
|
- LICENSE
|
64
80
|
- README.textile
|
65
81
|
- Rakefile
|
82
|
+
- assets/company_logos.png
|
66
83
|
- assets/images/buttons_lite_background.png
|
67
84
|
- assets/images/pager_arrow_left.gif
|
68
85
|
- assets/images/pager_arrow_left_off.gif
|
@@ -113,6 +130,7 @@ files:
|
|
113
130
|
- spec/dummy_app/app/views/products/index_filters.html.erb
|
114
131
|
- spec/dummy_app/app/views/products/index_select.html.erb
|
115
132
|
- spec/dummy_app/app/views/products/index_simple.html.erb
|
133
|
+
- spec/dummy_app/app/views/products/index_stateful.html.erb
|
116
134
|
- spec/dummy_app/app/views/products/new.html.erb
|
117
135
|
- spec/dummy_app/app/views/products/show.html.erb
|
118
136
|
- spec/dummy_app/app/views/vendors/_form.html.erb
|
@@ -183,20 +201,24 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
183
201
|
requirements:
|
184
202
|
- - ">="
|
185
203
|
- !ruby/object:Gem::Version
|
204
|
+
segments:
|
205
|
+
- 0
|
186
206
|
version: "0"
|
187
207
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
188
208
|
none: false
|
189
209
|
requirements:
|
190
210
|
- - ">="
|
191
211
|
- !ruby/object:Gem::Version
|
212
|
+
segments:
|
213
|
+
- 0
|
192
214
|
version: "0"
|
193
215
|
requirements: []
|
194
216
|
|
195
217
|
rubyforge_project: tabulatr
|
196
|
-
rubygems_version: 1.
|
218
|
+
rubygems_version: 1.3.7
|
197
219
|
signing_key:
|
198
220
|
specification_version: 3
|
199
|
-
summary:
|
221
|
+
summary: A tight DSL to build tables of ActiveRecord models with sorting, pagination, finding/filtering, selecting and batch actions.
|
200
222
|
test_files:
|
201
223
|
- spec/dummy_app/.gitignore
|
202
224
|
- spec/dummy_app/app/controllers/application_controller.rb
|
@@ -215,6 +237,7 @@ test_files:
|
|
215
237
|
- spec/dummy_app/app/views/products/index_filters.html.erb
|
216
238
|
- spec/dummy_app/app/views/products/index_select.html.erb
|
217
239
|
- spec/dummy_app/app/views/products/index_simple.html.erb
|
240
|
+
- spec/dummy_app/app/views/products/index_stateful.html.erb
|
218
241
|
- spec/dummy_app/app/views/products/new.html.erb
|
219
242
|
- spec/dummy_app/app/views/products/show.html.erb
|
220
243
|
- spec/dummy_app/app/views/vendors/_form.html.erb
|