smart_table 0.0.1
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 +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +171 -0
- data/LICENSE.txt +21 -0
- data/README.md +132 -0
- data/app/assets/javascripts/smart_table.js +137 -0
- data/app/assets/stylesheets/smart_table.scss +85 -0
- data/app/controllers/concerns/smart_table/smart_table_concern.rb +58 -0
- data/app/helpers/smart_table/smart_table_helper.rb +211 -0
- data/app/views/kaminari/smart_table/_first_page.html.erb +12 -0
- data/app/views/kaminari/smart_table/_gap.html.erb +8 -0
- data/app/views/kaminari/smart_table/_last_page.html.erb +12 -0
- data/app/views/kaminari/smart_table/_next_page.html.erb +12 -0
- data/app/views/kaminari/smart_table/_page.html.erb +10 -0
- data/app/views/kaminari/smart_table/_paginator.html.erb +25 -0
- data/app/views/kaminari/smart_table/_prev_page.html.erb +12 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/config/locales/smart_table.en.yml +25 -0
- data/config/locales/smart_table.pt.yml +25 -0
- data/lib/generators/init_generator.rb +16 -0
- data/lib/generators/templates/smart_table_initializer.rb +6 -0
- data/lib/smart_table/config.rb +15 -0
- data/lib/smart_table/engine.rb +21 -0
- data/lib/smart_table/version.rb +3 -0
- data/lib/smart_table.rb +28 -0
- data/smart_table-0.0.1.gem +0 -0
- data/smart_table.gemspec +33 -0
- data/spec/dummy_app/Rakefile +6 -0
- data/spec/dummy_app/app/assets/config/manifest.js +3 -0
- data/spec/dummy_app/app/assets/javascripts/application.js +15 -0
- data/spec/dummy_app/app/assets/javascripts/cable.js +13 -0
- data/spec/dummy_app/app/assets/stylesheets/application.css +15 -0
- data/spec/dummy_app/app/channels/application_cable/channel.rb +4 -0
- data/spec/dummy_app/app/channels/application_cable/connection.rb +4 -0
- data/spec/dummy_app/app/controllers/application_controller.rb +2 -0
- data/spec/dummy_app/app/helpers/application_helper.rb +2 -0
- data/spec/dummy_app/app/jobs/application_job.rb +2 -0
- data/spec/dummy_app/app/mailers/application_mailer.rb +4 -0
- data/spec/dummy_app/app/models/application_record.rb +3 -0
- data/spec/dummy_app/app/views/layouts/application.html.erb +15 -0
- data/spec/dummy_app/app/views/layouts/mailer.html.erb +13 -0
- data/spec/dummy_app/app/views/layouts/mailer.text.erb +1 -0
- data/spec/dummy_app/bin/bundle +3 -0
- data/spec/dummy_app/bin/rails +4 -0
- data/spec/dummy_app/bin/rake +4 -0
- data/spec/dummy_app/bin/setup +36 -0
- data/spec/dummy_app/bin/update +31 -0
- data/spec/dummy_app/bin/yarn +11 -0
- data/spec/dummy_app/config/application.rb +17 -0
- data/spec/dummy_app/config/boot.rb +5 -0
- data/spec/dummy_app/config/cable.yml +10 -0
- data/spec/dummy_app/config/database.yml +25 -0
- data/spec/dummy_app/config/environment.rb +5 -0
- data/spec/dummy_app/config/environments/development.rb +61 -0
- data/spec/dummy_app/config/environments/production.rb +94 -0
- data/spec/dummy_app/config/environments/test.rb +46 -0
- data/spec/dummy_app/config/initializers/application_controller_renderer.rb +8 -0
- data/spec/dummy_app/config/initializers/assets.rb +14 -0
- data/spec/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy_app/config/initializers/content_security_policy.rb +25 -0
- data/spec/dummy_app/config/initializers/cookies_serializer.rb +5 -0
- data/spec/dummy_app/config/initializers/filter_parameter_logging.rb +4 -0
- data/spec/dummy_app/config/initializers/inflections.rb +16 -0
- data/spec/dummy_app/config/initializers/mime_types.rb +4 -0
- data/spec/dummy_app/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy_app/config/locales/en.yml +33 -0
- data/spec/dummy_app/config/puma.rb +34 -0
- data/spec/dummy_app/config/routes.rb +3 -0
- data/spec/dummy_app/config/spring.rb +6 -0
- data/spec/dummy_app/config/storage.yml +34 -0
- data/spec/dummy_app/config.ru +5 -0
- data/spec/dummy_app/db/test.sqlite3 +0 -0
- data/spec/dummy_app/log/test.log +0 -0
- data/spec/dummy_app/package.json +5 -0
- data/spec/dummy_app/public/404.html +67 -0
- data/spec/dummy_app/public/422.html +67 -0
- data/spec/dummy_app/public/500.html +66 -0
- data/spec/dummy_app/public/apple-touch-icon-precomposed.png +0 -0
- data/spec/dummy_app/public/apple-touch-icon.png +0 -0
- data/spec/dummy_app/public/favicon.ico +0 -0
- data/spec/rails_helper.rb +13 -0
- data/spec/smart_table/app/controllers/concerns/smart_table_concern_spec.rb +104 -0
- data/spec/smart_table/app/helpers/smart_table_helper_spec.rb +48 -0
- data/spec/smart_table/lib/config_spec.rb +18 -0
- data/spec/smart_table/lib/engine_spec.rb +12 -0
- data/spec/smart_table_spec.rb +26 -0
- data/spec/spec_helper.rb +20 -0
- metadata +263 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 23acd51b4d9ed74656af184838af799679d1af671868a33ad8469d28fa07f120
|
|
4
|
+
data.tar.gz: 18cafc003a7009ec0851a82644cc165ac1f2f4cf0434201d71f20d51f6921f40
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f719177b8bc9d656a37fdb3809ad54b93c478f5a3f25a62a934fc9f196c88be002504d0b62137a3c5ca84ce013cd702b9266247826e3ad337564e79a08d8be62
|
|
7
|
+
data.tar.gz: 1f6f1ce141d46c6b02cf62fa1922079065d515fdc950746e002beaefee623c0afc41fc22b4275a70248e960c578fda5ce90047ea0d1c861927556334d7b37804
|
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
|
@@ -0,0 +1,171 @@
|
|
|
1
|
+
PATH
|
|
2
|
+
remote: .
|
|
3
|
+
specs:
|
|
4
|
+
smart_table (0.0.1)
|
|
5
|
+
font-awesome-rails
|
|
6
|
+
kaminari
|
|
7
|
+
rails (> 4.2.0, < 5.3.0)
|
|
8
|
+
|
|
9
|
+
GEM
|
|
10
|
+
remote: https://rubygems.org/
|
|
11
|
+
specs:
|
|
12
|
+
actioncable (5.2.0)
|
|
13
|
+
actionpack (= 5.2.0)
|
|
14
|
+
nio4r (~> 2.0)
|
|
15
|
+
websocket-driver (>= 0.6.1)
|
|
16
|
+
actionmailer (5.2.0)
|
|
17
|
+
actionpack (= 5.2.0)
|
|
18
|
+
actionview (= 5.2.0)
|
|
19
|
+
activejob (= 5.2.0)
|
|
20
|
+
mail (~> 2.5, >= 2.5.4)
|
|
21
|
+
rails-dom-testing (~> 2.0)
|
|
22
|
+
actionpack (5.2.0)
|
|
23
|
+
actionview (= 5.2.0)
|
|
24
|
+
activesupport (= 5.2.0)
|
|
25
|
+
rack (~> 2.0)
|
|
26
|
+
rack-test (>= 0.6.3)
|
|
27
|
+
rails-dom-testing (~> 2.0)
|
|
28
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.2)
|
|
29
|
+
actionview (5.2.0)
|
|
30
|
+
activesupport (= 5.2.0)
|
|
31
|
+
builder (~> 3.1)
|
|
32
|
+
erubi (~> 1.4)
|
|
33
|
+
rails-dom-testing (~> 2.0)
|
|
34
|
+
rails-html-sanitizer (~> 1.0, >= 1.0.3)
|
|
35
|
+
activejob (5.2.0)
|
|
36
|
+
activesupport (= 5.2.0)
|
|
37
|
+
globalid (>= 0.3.6)
|
|
38
|
+
activemodel (5.2.0)
|
|
39
|
+
activesupport (= 5.2.0)
|
|
40
|
+
activerecord (5.2.0)
|
|
41
|
+
activemodel (= 5.2.0)
|
|
42
|
+
activesupport (= 5.2.0)
|
|
43
|
+
arel (>= 9.0)
|
|
44
|
+
activestorage (5.2.0)
|
|
45
|
+
actionpack (= 5.2.0)
|
|
46
|
+
activerecord (= 5.2.0)
|
|
47
|
+
marcel (~> 0.3.1)
|
|
48
|
+
activesupport (5.2.0)
|
|
49
|
+
concurrent-ruby (~> 1.0, >= 1.0.2)
|
|
50
|
+
i18n (>= 0.7, < 2)
|
|
51
|
+
minitest (~> 5.1)
|
|
52
|
+
tzinfo (~> 1.1)
|
|
53
|
+
arel (9.0.0)
|
|
54
|
+
builder (3.2.3)
|
|
55
|
+
byebug (9.1.0)
|
|
56
|
+
concurrent-ruby (1.0.5)
|
|
57
|
+
crass (1.0.4)
|
|
58
|
+
diff-lcs (1.3)
|
|
59
|
+
erubi (1.7.1)
|
|
60
|
+
font-awesome-rails (4.7.0.4)
|
|
61
|
+
railties (>= 3.2, < 6.0)
|
|
62
|
+
globalid (0.4.1)
|
|
63
|
+
activesupport (>= 4.2.0)
|
|
64
|
+
i18n (1.0.1)
|
|
65
|
+
concurrent-ruby (~> 1.0)
|
|
66
|
+
kaminari (1.1.1)
|
|
67
|
+
activesupport (>= 4.1.0)
|
|
68
|
+
kaminari-actionview (= 1.1.1)
|
|
69
|
+
kaminari-activerecord (= 1.1.1)
|
|
70
|
+
kaminari-core (= 1.1.1)
|
|
71
|
+
kaminari-actionview (1.1.1)
|
|
72
|
+
actionview
|
|
73
|
+
kaminari-core (= 1.1.1)
|
|
74
|
+
kaminari-activerecord (1.1.1)
|
|
75
|
+
activerecord
|
|
76
|
+
kaminari-core (= 1.1.1)
|
|
77
|
+
kaminari-core (1.1.1)
|
|
78
|
+
loofah (2.2.2)
|
|
79
|
+
crass (~> 1.0.2)
|
|
80
|
+
nokogiri (>= 1.5.9)
|
|
81
|
+
mail (2.7.0)
|
|
82
|
+
mini_mime (>= 0.1.1)
|
|
83
|
+
marcel (0.3.2)
|
|
84
|
+
mimemagic (~> 0.3.2)
|
|
85
|
+
method_source (0.9.0)
|
|
86
|
+
mimemagic (0.3.2)
|
|
87
|
+
mini_mime (1.0.0)
|
|
88
|
+
mini_portile2 (2.3.0)
|
|
89
|
+
minitest (5.11.3)
|
|
90
|
+
nio4r (2.3.1)
|
|
91
|
+
nokogiri (1.8.4)
|
|
92
|
+
mini_portile2 (~> 2.3.0)
|
|
93
|
+
rack (2.0.5)
|
|
94
|
+
rack-test (1.0.0)
|
|
95
|
+
rack (>= 1.0, < 3)
|
|
96
|
+
rails (5.2.0)
|
|
97
|
+
actioncable (= 5.2.0)
|
|
98
|
+
actionmailer (= 5.2.0)
|
|
99
|
+
actionpack (= 5.2.0)
|
|
100
|
+
actionview (= 5.2.0)
|
|
101
|
+
activejob (= 5.2.0)
|
|
102
|
+
activemodel (= 5.2.0)
|
|
103
|
+
activerecord (= 5.2.0)
|
|
104
|
+
activestorage (= 5.2.0)
|
|
105
|
+
activesupport (= 5.2.0)
|
|
106
|
+
bundler (>= 1.3.0)
|
|
107
|
+
railties (= 5.2.0)
|
|
108
|
+
sprockets-rails (>= 2.0.0)
|
|
109
|
+
rails-dom-testing (2.0.3)
|
|
110
|
+
activesupport (>= 4.2.0)
|
|
111
|
+
nokogiri (>= 1.6)
|
|
112
|
+
rails-html-sanitizer (1.0.4)
|
|
113
|
+
loofah (~> 2.2, >= 2.2.2)
|
|
114
|
+
railties (5.2.0)
|
|
115
|
+
actionpack (= 5.2.0)
|
|
116
|
+
activesupport (= 5.2.0)
|
|
117
|
+
method_source
|
|
118
|
+
rake (>= 0.8.7)
|
|
119
|
+
thor (>= 0.18.1, < 2.0)
|
|
120
|
+
rake (12.3.1)
|
|
121
|
+
rspec (3.7.0)
|
|
122
|
+
rspec-core (~> 3.7.0)
|
|
123
|
+
rspec-expectations (~> 3.7.0)
|
|
124
|
+
rspec-mocks (~> 3.7.0)
|
|
125
|
+
rspec-core (3.7.1)
|
|
126
|
+
rspec-support (~> 3.7.0)
|
|
127
|
+
rspec-expectations (3.7.0)
|
|
128
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
129
|
+
rspec-support (~> 3.7.0)
|
|
130
|
+
rspec-mocks (3.7.0)
|
|
131
|
+
diff-lcs (>= 1.2.0, < 2.0)
|
|
132
|
+
rspec-support (~> 3.7.0)
|
|
133
|
+
rspec-rails (3.7.2)
|
|
134
|
+
actionpack (>= 3.0)
|
|
135
|
+
activesupport (>= 3.0)
|
|
136
|
+
railties (>= 3.0)
|
|
137
|
+
rspec-core (~> 3.7.0)
|
|
138
|
+
rspec-expectations (~> 3.7.0)
|
|
139
|
+
rspec-mocks (~> 3.7.0)
|
|
140
|
+
rspec-support (~> 3.7.0)
|
|
141
|
+
rspec-support (3.7.1)
|
|
142
|
+
sprockets (3.7.2)
|
|
143
|
+
concurrent-ruby (~> 1.0)
|
|
144
|
+
rack (> 1, < 3)
|
|
145
|
+
sprockets-rails (3.2.1)
|
|
146
|
+
actionpack (>= 4.0)
|
|
147
|
+
activesupport (>= 4.0)
|
|
148
|
+
sprockets (>= 3.0.0)
|
|
149
|
+
sqlite3 (1.3.13)
|
|
150
|
+
thor (0.20.0)
|
|
151
|
+
thread_safe (0.3.6)
|
|
152
|
+
tzinfo (1.2.5)
|
|
153
|
+
thread_safe (~> 0.1)
|
|
154
|
+
websocket-driver (0.7.0)
|
|
155
|
+
websocket-extensions (>= 0.1.0)
|
|
156
|
+
websocket-extensions (0.1.3)
|
|
157
|
+
|
|
158
|
+
PLATFORMS
|
|
159
|
+
ruby
|
|
160
|
+
|
|
161
|
+
DEPENDENCIES
|
|
162
|
+
bundler (~> 1.16)
|
|
163
|
+
byebug (~> 9)
|
|
164
|
+
rake (~> 12.0)
|
|
165
|
+
rspec (~> 3.0)
|
|
166
|
+
rspec-rails (~> 3.7)
|
|
167
|
+
smart_table!
|
|
168
|
+
sqlite3
|
|
169
|
+
|
|
170
|
+
BUNDLED WITH
|
|
171
|
+
1.16.2
|
data/LICENSE.txt
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
The MIT License (MIT)
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2018 Henrique Gubert
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in
|
|
13
|
+
all copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
|
21
|
+
THE SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# SmartTable
|
|
2
|
+
|
|
3
|
+
Implements tables with pagination and search for Rails, with server-side content loading.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
Add this line to your application's Gemfile:
|
|
7
|
+
|
|
8
|
+
```ruby
|
|
9
|
+
gem 'smart_table'
|
|
10
|
+
```
|
|
11
|
+
|
|
12
|
+
And then execute:
|
|
13
|
+
```
|
|
14
|
+
bundle
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Getting Started
|
|
18
|
+
|
|
19
|
+
### Including Assets
|
|
20
|
+
SmartTable uses both JS and CSS, that must be included in your app's asset pipeline.
|
|
21
|
+
```
|
|
22
|
+
// Add this to your application.js or vendor.js
|
|
23
|
+
//= require smart_table
|
|
24
|
+
|
|
25
|
+
// Add this to your application.scss or vendor.scss
|
|
26
|
+
*= require smart_table
|
|
27
|
+
```
|
|
28
|
+
|
|
29
|
+
### Setting up the Controller
|
|
30
|
+
Add this line to your index action:
|
|
31
|
+
```ruby
|
|
32
|
+
def index
|
|
33
|
+
smart_table_params = smart_table_params(initial_page_size: 20)
|
|
34
|
+
|
|
35
|
+
...
|
|
36
|
+
end
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
You can now use the `smart_table_params` object to customize your record's loading and counting:
|
|
40
|
+
```ruby
|
|
41
|
+
# smart_table_params.search => string typed by user on search box (might be nil or empty)
|
|
42
|
+
# smart_table_params.sort => string in the format of 'attribute ASC' or 'attribute DESC' (might be nil if there is no sorting specified)
|
|
43
|
+
# smart_table_params.limit => page size (nil if showing all records)
|
|
44
|
+
# smart_table_params.offset => record offset based on page number (nil if showing all records)
|
|
45
|
+
|
|
46
|
+
@current_page_records = Record.
|
|
47
|
+
where('column1 LIKE ? OR column2 LIKE ?', *Array.new(2, "%#{ActiveRecord::Base.sanitize_sql_like(smart_table_params.search)}%")).
|
|
48
|
+
order(smart_table_params.sort).
|
|
49
|
+
limit(smart_table_params.limit).
|
|
50
|
+
offset(smart_table_params.offset)
|
|
51
|
+
|
|
52
|
+
# Besides loading the records of the current page, the smart_table gem requires you
|
|
53
|
+
# to count the total number of records of the table, so it can build the pagination
|
|
54
|
+
# controls properly. Any filtering applied to record loading must be applied to
|
|
55
|
+
# counting as well.
|
|
56
|
+
@total_records_count = Record.
|
|
57
|
+
where('column1 LIKE ? OR column2 LIKE ?', *Array.new(2, "%#{ActiveRecord::Base.sanitize_sql_like(smart_table_params.search)}%")).
|
|
58
|
+
count
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
You can also use the `smart_table_params` to load/count records from another source, like an API or a NoSQL database. It is all up to you!
|
|
62
|
+
|
|
63
|
+
### Setting up the View
|
|
64
|
+
Now in your view, use the following helpers to enhance your table:
|
|
65
|
+
|
|
66
|
+
```html
|
|
67
|
+
<h1>Users</h1>
|
|
68
|
+
|
|
69
|
+
<div>
|
|
70
|
+
<%# Renders text field for searching %>
|
|
71
|
+
<%= smart_table_search %>
|
|
72
|
+
</div>
|
|
73
|
+
|
|
74
|
+
<table class='table'>
|
|
75
|
+
<thead>
|
|
76
|
+
<tr>
|
|
77
|
+
<th></th>
|
|
78
|
+
<th><%= smart_table_sortable("Username", :username) %></th>
|
|
79
|
+
<th><%= smart_table_sortable("Email", :email) %></th>
|
|
80
|
+
<th><%= smart_table_sortable("Name", :name) %></th>
|
|
81
|
+
<th><%= User.human_attribute_name(:account_type) %></th> <%# this column is not sortable %>
|
|
82
|
+
</tr>
|
|
83
|
+
</thead>
|
|
84
|
+
<tbody>
|
|
85
|
+
<% @current_page_users.each do |user| %>
|
|
86
|
+
<tr>
|
|
87
|
+
<td><%= link_to "show", user_path(user) %></td>
|
|
88
|
+
<td><%= user.username %></td>
|
|
89
|
+
<td><%= user.email %></td>
|
|
90
|
+
<td><%= user.name %></td>
|
|
91
|
+
<td><%= user.account_type %></td>
|
|
92
|
+
</tr>
|
|
93
|
+
<% end %>
|
|
94
|
+
</tbody>
|
|
95
|
+
</table>
|
|
96
|
+
|
|
97
|
+
<%# Renders pagination controls (page numbers, previous/next buttons, etc) %>
|
|
98
|
+
<%# Requires both the records of the current page (@users) and the total count %>
|
|
99
|
+
<%= smart_table_paginate @current_page_users, @total_users_count, User.model_name.human %>
|
|
100
|
+
|
|
101
|
+
<%# Renders page size selector (depends on total record count) %>
|
|
102
|
+
<%= smart_table_page_size_selector @total_user_count, User.model_name.human %>
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
This should be enough for your smart table to function properly.
|
|
106
|
+
|
|
107
|
+
### Adding Extra Filters
|
|
108
|
+
|
|
109
|
+
Sometimes a single search box is not enough. You want to provide users more advanced filtering options. In this case you can use the `smart_table_extra_filters` helpers to wrap a set of fields, that will automatically trigger a a page refresh when changed, including the field value itself in the `params` hash.
|
|
110
|
+
|
|
111
|
+
You must handle the `params` hash by yourself in the controller (you will probably change the way you load your records, based on those parameters).
|
|
112
|
+
|
|
113
|
+
The following snippet shows how to use different input types to make custom filters.
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
<%# Renders text field for searching %>
|
|
117
|
+
<%= smart_table_extra_filters do %>
|
|
118
|
+
<%# Checkbox %>
|
|
119
|
+
<%= check_box_tag 'somekey', 'value', params['somekey'] %>
|
|
120
|
+
|
|
121
|
+
<%# Select box %>
|
|
122
|
+
<%= select_tag "credit_card", options_for_select({"VISA" => 'visa', "MasterCard" => 'master_card'}, params['credit_card']) %>
|
|
123
|
+
|
|
124
|
+
<%# Text field %>
|
|
125
|
+
<%= text_field_tag "somefield", params['somefield'] %>
|
|
126
|
+
|
|
127
|
+
<%# Radio buttons %>
|
|
128
|
+
<%= radio_button_tag("category", "", !params["category"].present?) %>
|
|
129
|
+
<%= radio_button_tag("category", "rails", params["category"] == 'rails') %>
|
|
130
|
+
<%= radio_button_tag("category", "java", params["category"] == 'java') %>
|
|
131
|
+
<% end %>
|
|
132
|
+
```
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
|
|
2
|
+
// SmartTable class constructor (empty)
|
|
3
|
+
var SmartTable = function() {
|
|
4
|
+
}
|
|
5
|
+
|
|
6
|
+
// Helper function to setup onLoad
|
|
7
|
+
SmartTable.onPageLoad = function(callback){
|
|
8
|
+
// modern browsers
|
|
9
|
+
if (document.addEventListener) {
|
|
10
|
+
document.addEventListener('DOMContentLoaded', callback);
|
|
11
|
+
document.addEventListener("turbolinks:load", callback); // Turbolinks 5
|
|
12
|
+
document.addEventListener("page:load", callback); // Turbolinks classic
|
|
13
|
+
}
|
|
14
|
+
// IE <= 8
|
|
15
|
+
else {
|
|
16
|
+
document.attachEvent('onreadystatechange', function() {
|
|
17
|
+
if (document.readyState == 'complete') callback();
|
|
18
|
+
});
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
// On page load, we setup search field and extra filters
|
|
23
|
+
SmartTable.onPageLoad(function() {
|
|
24
|
+
SmartTable.setupSmartTableSearch();
|
|
25
|
+
SmartTable.setupSmartTableExtraFilters();
|
|
26
|
+
})
|
|
27
|
+
|
|
28
|
+
// Gets the current page url and merges some query parameters to this url. If a
|
|
29
|
+
// certain parameter already exists, it is overwritten. If the value of the
|
|
30
|
+
// parameter in the argument map is "null", the parameter is removed from the url.
|
|
31
|
+
// params: object containing parameters to be included in the url.
|
|
32
|
+
SmartTable.currentUrlWithMergedQueryParams = function(params) {
|
|
33
|
+
// parses url and its query params
|
|
34
|
+
var location = window.location;
|
|
35
|
+
var vars = location.search.substring(1).split('&');
|
|
36
|
+
var queryParams = {};
|
|
37
|
+
if (!!vars && vars.length >0 && vars[0] != "") {
|
|
38
|
+
for (var i=0; i<vars.length; i++) {
|
|
39
|
+
var pair = vars[i].split('=');
|
|
40
|
+
|
|
41
|
+
// decodeURIComponent does not decode '+' into space, so we do some preprocessing
|
|
42
|
+
// and replace '+' for '%20', which is decoded to space by decodeURIComponent
|
|
43
|
+
pair[1] = pair[1].replace(/\+/g, '%20');
|
|
44
|
+
|
|
45
|
+
queryParams[decodeURIComponent(pair[0])] = decodeURIComponent(pair[1]);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// merges received params
|
|
50
|
+
for (var key in params) {
|
|
51
|
+
if (params[key] != null) {
|
|
52
|
+
queryParams[key] = params[key];
|
|
53
|
+
} else {
|
|
54
|
+
delete queryParams[key];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
// rebuilds url
|
|
59
|
+
var newSearchString = null;
|
|
60
|
+
for (var key in queryParams) {
|
|
61
|
+
if (newSearchString == null) {
|
|
62
|
+
newSearchString = "?";
|
|
63
|
+
} else {
|
|
64
|
+
newSearchString += "&";
|
|
65
|
+
}
|
|
66
|
+
newSearchString += encodeURIComponent(key) + "=" + encodeURIComponent(queryParams[key]);
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// returns new url
|
|
70
|
+
return location.origin + location.pathname + newSearchString;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
// Refreshes the current page, adding a pair of key value to the url's query string.
|
|
74
|
+
// If value is "null", the parameter is removed from the url.
|
|
75
|
+
// It also adds an extra parameter "st_page" so the table goes back to first
|
|
76
|
+
// page
|
|
77
|
+
SmartTable.refreshPageWithParam = function(key, value) {
|
|
78
|
+
var params = {
|
|
79
|
+
st_page: 1,
|
|
80
|
+
}
|
|
81
|
+
if (!!value && value.length > 0) {
|
|
82
|
+
params[key] = value;
|
|
83
|
+
} else {
|
|
84
|
+
params[key] = null;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// makes the request
|
|
88
|
+
window.location = SmartTable.currentUrlWithMergedQueryParams(params);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Prepares table search field, so the table is refreshed when the field changes
|
|
92
|
+
SmartTable.setupSmartTableSearch = function() {
|
|
93
|
+
// gets search text field
|
|
94
|
+
var smartTableSearch = document.getElementById('smart_table_search');
|
|
95
|
+
if (!smartTableSearch) return;
|
|
96
|
+
|
|
97
|
+
// refreshes page every time search field changes
|
|
98
|
+
smartTableSearch.addEventListener('change', function(event) {
|
|
99
|
+
// get search string from field value
|
|
100
|
+
var searchString = event.currentTarget.value;
|
|
101
|
+
SmartTable.refreshPageWithParam("st_search", searchString);
|
|
102
|
+
});
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// Prepares table extra filters section, so the table is refreshed when the
|
|
106
|
+
// any of the input fields are changed
|
|
107
|
+
SmartTable.setupSmartTableExtraFilters = function() {
|
|
108
|
+
var smartTableExtraFilters = document.getElementById('smart_table_extra_filters');
|
|
109
|
+
if (!smartTableExtraFilters) return;
|
|
110
|
+
|
|
111
|
+
// all input fields
|
|
112
|
+
var inputNodes = smartTableExtraFilters.getElementsByTagName('input');
|
|
113
|
+
var selectNodes = smartTableExtraFilters.getElementsByTagName('select');
|
|
114
|
+
var nodeCollections = [inputNodes, selectNodes];
|
|
115
|
+
|
|
116
|
+
// refreshes page every time any field changes
|
|
117
|
+
for (var i=0; i<nodeCollections.length; i++) {
|
|
118
|
+
var nodeCollection = nodeCollections[i];
|
|
119
|
+
for (var j=0; j<nodeCollection.length; j++) {
|
|
120
|
+
var node = nodeCollection[j];
|
|
121
|
+
node.addEventListener('change', function(event) {
|
|
122
|
+
if (event.target.type == 'checkbox' || event.target.type == 'radio') {
|
|
123
|
+
var checkboxOrRadio = event.target;
|
|
124
|
+
SmartTable.refreshPageWithParam(checkboxOrRadio.name, (checkboxOrRadio.checked ? checkboxOrRadio.value : ""));
|
|
125
|
+
}
|
|
126
|
+
else if (event.target.type == 'text') {
|
|
127
|
+
var textField = event.target;
|
|
128
|
+
SmartTable.refreshPageWithParam(textField.name, textField.value);
|
|
129
|
+
}
|
|
130
|
+
else if (event.target.type == 'select-one') {
|
|
131
|
+
var select = event.target;
|
|
132
|
+
SmartTable.refreshPageWithParam(select.name, select.value);
|
|
133
|
+
}
|
|
134
|
+
});
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
}
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
|
|
2
|
+
ul.pagination {
|
|
3
|
+
display: inline-block;
|
|
4
|
+
padding-left: 0;
|
|
5
|
+
margin: 10px 0;
|
|
6
|
+
border-radius: 4px;
|
|
7
|
+
|
|
8
|
+
// Pagination buttons
|
|
9
|
+
&>a {
|
|
10
|
+
position: relative;
|
|
11
|
+
float: left;
|
|
12
|
+
line-height: 1.428571429;
|
|
13
|
+
padding: 6px 12px;
|
|
14
|
+
text-decoration: none;
|
|
15
|
+
color: #616161;
|
|
16
|
+
background-color: white;
|
|
17
|
+
border: 1px solid #dddddd;
|
|
18
|
+
margin-left: -1px;
|
|
19
|
+
|
|
20
|
+
// First pagination button
|
|
21
|
+
&:first-child {
|
|
22
|
+
margin-left: 0;
|
|
23
|
+
border-bottom-left-radius: 4px;
|
|
24
|
+
border-top-left-radius: 4px;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// Last pagination button
|
|
28
|
+
&:last-child {
|
|
29
|
+
margin-left: 0;
|
|
30
|
+
border-bottom-right-radius: 4px;
|
|
31
|
+
border-top-right-radius: 4px;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
// Currently selected button
|
|
35
|
+
&.current {
|
|
36
|
+
z-index: 2;
|
|
37
|
+
color: white;
|
|
38
|
+
background-color: #616161;
|
|
39
|
+
border-color: #616161;
|
|
40
|
+
cursor: default;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
// currently hovered button (except if selected)
|
|
44
|
+
&:hover:not(.current) {
|
|
45
|
+
color: #245151;
|
|
46
|
+
background-color: #eeeeee;
|
|
47
|
+
border-color: #dddddd;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
// links inside buttons {
|
|
51
|
+
&>a {
|
|
52
|
+
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// style for a pretty text field
|
|
58
|
+
@mixin smart_table_text_field {
|
|
59
|
+
height: 34px;
|
|
60
|
+
padding: 6px 12px;
|
|
61
|
+
font-size: 14px;
|
|
62
|
+
line-height: 1.428571429;
|
|
63
|
+
color: #555555;
|
|
64
|
+
background-color: white;
|
|
65
|
+
background-image: none;
|
|
66
|
+
border: 1px solid #cccccc;
|
|
67
|
+
border-radius: 4px;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
// search field: right aligned
|
|
71
|
+
.smart_table_search {
|
|
72
|
+
@include smart_table_text_field;
|
|
73
|
+
float: right;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.smart_table_extra_filters {
|
|
77
|
+
// text fields and select boxes inside extra filters
|
|
78
|
+
input[type="text"], select {
|
|
79
|
+
@include smart_table_text_field;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
.text-center {
|
|
84
|
+
text-align: center;
|
|
85
|
+
}
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
|
|
2
|
+
module SmartTable
|
|
3
|
+
module SmartTableConcern
|
|
4
|
+
extend ActiveSupport::Concern
|
|
5
|
+
|
|
6
|
+
included do
|
|
7
|
+
helper_method :get_cached_smart_table_params
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
class Params
|
|
11
|
+
attr_accessor :sort, :page_size, :page_number, :search
|
|
12
|
+
|
|
13
|
+
def initialize
|
|
14
|
+
self.sort = nil
|
|
15
|
+
self.page_size = nil
|
|
16
|
+
self.page_number = 1
|
|
17
|
+
self.search = nil
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def limit
|
|
21
|
+
page_size
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def offset
|
|
25
|
+
page_size * (page_number-1) if page_size
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def smart_table_params(initial_page_size: 25)
|
|
30
|
+
return @st_params if @st_params
|
|
31
|
+
|
|
32
|
+
@st_params = Params.new
|
|
33
|
+
@st_params.sort = params[SORT_PARAM]
|
|
34
|
+
@st_params.search = params[SEARCH_PARAM]
|
|
35
|
+
@st_params.page_size = params[PAGE_SIZE_PARAM] || initial_page_size
|
|
36
|
+
if @st_params.page_size == SHOW_ALL
|
|
37
|
+
@st_params.page_size = nil
|
|
38
|
+
else
|
|
39
|
+
@st_params.page_size = @st_params.page_size.to_i
|
|
40
|
+
|
|
41
|
+
if params[PAGE_PARAM].present? && params[PAGE_PARAM] =~ /\d+/
|
|
42
|
+
page = params[PAGE_PARAM].to_i
|
|
43
|
+
page = 1 if page < 1
|
|
44
|
+
@st_params.page_number = page
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
@st_params
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
private
|
|
52
|
+
|
|
53
|
+
def get_cached_smart_table_params
|
|
54
|
+
@st_params
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
end
|
|
58
|
+
end
|