tabulatr2 0.9.16 → 0.9.17
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -0
- data/app/assets/javascripts/tabulatr/_tabulatr.js +21 -8
- data/app/views/tabulatr/_tabulatr_batch_actions_menu.html.slim +1 -1
- data/app/views/tabulatr/_tabulatr_filter_dialog.html.slim +8 -1
- data/lib/tabulatr/data/data.rb +10 -8
- data/lib/tabulatr/data/filtering.rb +24 -12
- data/lib/tabulatr/renderer/column.rb +11 -9
- data/lib/tabulatr/renderer/renderer.rb +9 -9
- data/lib/tabulatr/version.rb +1 -1
- data/lib/tabulatr.rb +3 -2
- data/spec/dummy/config/environments/production.rb +1 -1
- data/spec/dummy/config/environments/test.rb +1 -1
- data/spec/dummy/config/locales/tabulatr.yml +2 -0
- data/spec/features/tabulatrs_spec.rb +12 -0
- data/spec/lib/tabulatr/data/data_spec.rb +14 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 28a75cdd6eebb48110ace894527bd211edb4bec0
|
4
|
+
data.tar.gz: 6d553772fe2733c6e6f129ce5f05296d0fbeb520
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 677da86fdeedcbab796ba3904e5e27e34d881ac3f8b38d954b49143dc7635c513af0a4186eb3f4f45757466b21b1c3cf1d7ecad690d54e4ecb445a4ada400101
|
7
|
+
data.tar.gz: a14ec3f70fe10b9ea241f8c608d78b39dbb7f89b57e3386a77a979c1ad13e11acfe6a7485d221b591dc65567432c5e26e0054ed5d31b25e62b3dedc924c1aec3
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,17 @@
|
|
1
|
+
## 0.9.17
|
2
|
+
* If a batch action is executed without checking any rows it
|
3
|
+
will be applied to all rows in the current filter
|
4
|
+
|
5
|
+
* Add filter `enum_multiselect`
|
6
|
+
|
7
|
+
Example:
|
8
|
+
```
|
9
|
+
column :status, filter: :enum_multiselect
|
10
|
+
```
|
11
|
+
|
12
|
+
## 0.9.16
|
13
|
+
Adds `paginate` as config option
|
14
|
+
|
1
15
|
## 0.9.15
|
2
16
|
* Adds filter support for `enum`
|
3
17
|
If it detects an enum it creates a dropdown filter with the possible enum
|
@@ -256,7 +256,14 @@ Tabulatr.prototype = {
|
|
256
256
|
var form_array = $('.tabulatr_filter_form[data-table="'+ this.id +'"]')
|
257
257
|
.find('input:visible,select:visible,input[type=hidden]').serializeArray();
|
258
258
|
for(var i = 0; i < form_array.length; i++){
|
259
|
-
hash[form_array[i].name]
|
259
|
+
if(hash[form_array[i].name] !== undefined){
|
260
|
+
if(!Array.isArray(hash[form_array[i].name])){
|
261
|
+
hash[form_array[i].name] = [hash[form_array[i].name]];
|
262
|
+
}
|
263
|
+
hash[form_array[i].name].push(form_array[i].value);
|
264
|
+
}else{
|
265
|
+
hash[form_array[i].name] = form_array[i].value;
|
266
|
+
}
|
260
267
|
}
|
261
268
|
return hash;
|
262
269
|
},
|
@@ -347,15 +354,21 @@ $(document).on('ready page:load', function(){
|
|
347
354
|
var params = {page: 1};
|
348
355
|
params[name] = key;
|
349
356
|
params.tabulatr_checked = {checked_ids: jQuery.map($('#'+ tableId +' .tabulatr-checkbox:checked'), function(el){return $(el).val();}).join(',')};
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
|
355
|
-
|
357
|
+
var confirmation = true;
|
358
|
+
if(params.tabulatr_checked.checked_ids == ''){
|
359
|
+
confirmation = confirm(a.parents('ul').data('confirm-text'));
|
360
|
+
}
|
361
|
+
if(confirmation){
|
362
|
+
$('.tabulatr_mark_all[data-table='+ tableId +']').prop('indeterminate', false).prop('checked', false);
|
363
|
+
$('#'+ tableId +' .tabulatr-wrench').addClass('disabled');
|
364
|
+
var table_obj;
|
365
|
+
for(var i = 0; i < tabulatr_tables.length; i++){
|
366
|
+
if(tabulatr_tables[i].id === tableId){
|
367
|
+
table_obj = tabulatr_tables[i];
|
368
|
+
}
|
356
369
|
}
|
370
|
+
table_obj.updateTable(params, true);
|
357
371
|
}
|
358
|
-
table_obj.updateTable(params, true);
|
359
372
|
});
|
360
373
|
|
361
374
|
$('form.tabulatr-fuzzy-search').submit(function(){
|
@@ -25,7 +25,7 @@
|
|
25
25
|
a.btn.btn-default data-toggle="dropdown" href="#"
|
26
26
|
i.icon-cog.glyphicon.glyphicon-cog.fa.fa-cog>
|
27
27
|
i.icon-caret-down.glyphicon.glyphicon-chevron-down.fa.fa-caret-down
|
28
|
-
ul.dropdown-menu role="menu" aria-labelledby="dLabel"
|
28
|
+
ul.dropdown-menu role="menu" aria-labelledby="dLabel" data-confirm-text=t('tabulatr.batch_confirm_text')
|
29
29
|
- table_options[:batch_actions].each do |key, label|
|
30
30
|
li
|
31
31
|
= link_to label, '#', class: "batch-action-inputs", data: { \
|
@@ -66,7 +66,7 @@
|
|
66
66
|
[t('tabulatr.boolean_filter.no'), "false"],
|
67
67
|
[t('tabulatr.boolean_filter.yes'), "true"]] \
|
68
68
|
), class: 'form-control no-chosen')
|
69
|
-
- elsif column.filter
|
69
|
+
- elsif [:exact, :integer, :decimal].member? column.filter
|
70
70
|
input.tabulatr_filter.form-control type="text" id="#{name}_exact" data-tabulatr-attribute="#{name}" name="#{iname}"
|
71
71
|
- elsif column.filter == :date
|
72
72
|
select.form-control.no-chosen name="#{iname}[date][simple]" data-tabulatr-date-filter="#{formatted_name}_#{name}_filter"
|
@@ -94,5 +94,12 @@
|
|
94
94
|
option= I18n.t('tabulatr.enum_filter.none')
|
95
95
|
- column.klass.try(column.name.to_s.pluralize.to_sym).each do |key, value|
|
96
96
|
option value=value = key
|
97
|
+
- elsif column.filter == :enum_multiselect
|
98
|
+
- column.klass.try(column.name.to_s.pluralize.to_sym).each do |key, value|
|
99
|
+
.row
|
100
|
+
.col-xs-2
|
101
|
+
= check_box_tag "#{iname}[]", value, true, {id: "check_box_#{key}"}
|
102
|
+
.col-xs-10
|
103
|
+
= label_tag "check_box_#{key}", key
|
97
104
|
- else
|
98
105
|
input.tabulatr_filter.form-control type="text" data-tabulatr-attribute="#{name}" name="#{iname}[like]"
|
data/lib/tabulatr/data/data.rb
CHANGED
@@ -43,7 +43,6 @@ class Tabulatr::Data
|
|
43
43
|
|
44
44
|
@batch_actions = block if block_given?
|
45
45
|
|
46
|
-
execute_batch_actions(batch_params(params), check_params(params))
|
47
46
|
|
48
47
|
# count
|
49
48
|
total = @relation.count
|
@@ -54,11 +53,11 @@ class Tabulatr::Data
|
|
54
53
|
apply_sorting(sort_params params)
|
55
54
|
join_required_tables(params)
|
56
55
|
|
56
|
+
execute_batch_actions(batch_params(params), check_params(params))
|
57
|
+
|
57
58
|
pagination = compute_pagination(params[:page], params[:pagesize])
|
58
59
|
apply_pagination(pagination.slice(:offset, :pagesize))
|
59
60
|
|
60
|
-
# TODO: batch actions and checked ids
|
61
|
-
|
62
61
|
# get the records
|
63
62
|
found = apply_formats(locals: locals, controller: controller)
|
64
63
|
|
@@ -87,6 +86,7 @@ class Tabulatr::Data
|
|
87
86
|
def execute_batch_actions batch_param, selected_ids
|
88
87
|
if batch_param.present? && @batch_actions.present?
|
89
88
|
batch_param = batch_param.keys.first.to_sym if batch_param.is_a?(Hash)
|
89
|
+
selected_ids = @relation.map(&:id) if selected_ids.empty?
|
90
90
|
@batch_actions.yield(Invoker.new(batch_param, selected_ids))
|
91
91
|
end
|
92
92
|
end
|
@@ -115,11 +115,13 @@ class Tabulatr::Data
|
|
115
115
|
end
|
116
116
|
|
117
117
|
def join_required_tables(params)
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
118
|
+
if params[:arguments].present?
|
119
|
+
tt = (params[:arguments].split(",").select{|s| s[':']}.map do |s|
|
120
|
+
s.split(':').first
|
121
|
+
end.uniq.map(&:to_sym))
|
122
|
+
tt.delete(@table_name.to_sym)
|
123
|
+
@includes = @includes + tt
|
124
|
+
end
|
123
125
|
# @relation = @relation.includes(@includes.map(&:to_sym)).references(@includes.map(&:to_sym))
|
124
126
|
@relation = @relation.eager_load(@includes.map(&:to_sym))
|
125
127
|
# @relation = @relation.group("#{@table_name}.#{@base.primary_key}")
|
@@ -66,19 +66,25 @@ module Tabulatr::Data::Filtering
|
|
66
66
|
end
|
67
67
|
|
68
68
|
def apply_condition(n,v)
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
69
|
+
case n.filter
|
70
|
+
when :checkbox then apply_boolean_condition(n, v)
|
71
|
+
when :decimal then apply_string_condition("#{n.filter_sql} = ?", v.to_f)
|
72
|
+
when :integer then apply_string_condition("#{n.filter_sql} = ?", v.to_i)
|
73
|
+
when :enum then apply_string_condition("#{n.filter_sql} = ?", v.to_i)
|
74
|
+
when :enum_multiselect then apply_array_condition(n, v)
|
75
|
+
when :exact then apply_string_condition("#{n.filter_sql} = ?", v)
|
76
|
+
when :like then apply_like_condition(n, v[:like])
|
77
|
+
when :date then apply_date_condition(n, v[:date])
|
78
|
+
when :range then apply_range_condition(n, v)
|
79
|
+
else raise "Wrong filter type for #{n.name}: #{n.filter}"
|
77
80
|
end
|
78
81
|
end
|
79
82
|
|
83
|
+
def apply_boolean_condition(n, value)
|
84
|
+
@relation = @relation.where("#{n.filter_sql} = ?", Tabulatr::Utility.string_to_boolean(value))
|
85
|
+
end
|
86
|
+
|
80
87
|
def apply_date_condition(n, cond)
|
81
|
-
return unless cond.present?
|
82
88
|
today = Date.today
|
83
89
|
case cond[:simple]
|
84
90
|
when 'none' then return
|
@@ -112,14 +118,20 @@ module Tabulatr::Data::Filtering
|
|
112
118
|
@relation = @relation.where(replacement_string, value) if value.present?
|
113
119
|
end
|
114
120
|
|
115
|
-
def
|
121
|
+
def apply_like_condition(column_name, value)
|
116
122
|
like ||= Tabulatr::Utility.like_statement
|
117
|
-
apply_string_condition("#{column_name.filter_sql} #{like} ?", "%#{
|
118
|
-
|
123
|
+
apply_string_condition("#{column_name.filter_sql} #{like} ?", "%#{value}%") if value.present?
|
124
|
+
end
|
125
|
+
|
126
|
+
def apply_range_condition(column_name, hash)
|
119
127
|
apply_string_condition("#{column_name.filter_sql} >= ?", "#{hash[:from]}")
|
120
128
|
apply_string_condition("#{column_name.filter_sql} <= ?", "#{hash[:to]}")
|
121
129
|
end
|
122
130
|
|
131
|
+
def apply_array_condition(column, value)
|
132
|
+
@relation = @relation.where(column.table_name => { column.name => value })
|
133
|
+
end
|
134
|
+
|
123
135
|
private
|
124
136
|
|
125
137
|
def execute_provided_search_block!(query)
|
@@ -180,19 +180,21 @@ class Tabulatr::Renderer::Column
|
|
180
180
|
end
|
181
181
|
|
182
182
|
def determine_appropriate_filter!
|
183
|
-
|
184
|
-
|
183
|
+
typ = self.klass.columns_hash[self.name.to_s].try(:type).try(:to_sym)
|
184
|
+
case typ
|
185
|
+
when :integer
|
185
186
|
if self.klass.respond_to?(:defined_enums) && self.klass.defined_enums.keys.include?(self.name.to_s)
|
186
187
|
self.filter = :enum
|
187
188
|
else
|
188
|
-
self.filter = :
|
189
|
+
self.filter = :integer
|
189
190
|
end
|
190
|
-
when :
|
191
|
-
|
192
|
-
when :
|
193
|
-
|
194
|
-
when :boolean
|
195
|
-
|
191
|
+
when :enum then self.filter = :enum
|
192
|
+
when :float, :decimal then self.filter = :decimal
|
193
|
+
when :string, :text then self.filter = :like
|
194
|
+
when :date, :time, :datetime, :timestamp then self.filter = :date
|
195
|
+
when :boolean then self.filter = :checkbox
|
196
|
+
when nil then self.filter = :exact
|
197
|
+
else raise "Unknown filter type for #{self.name}: »#{typ}«"
|
196
198
|
end
|
197
199
|
end
|
198
200
|
|
@@ -24,15 +24,15 @@
|
|
24
24
|
class Tabulatr::Renderer
|
25
25
|
|
26
26
|
def initialize(klass, view,
|
27
|
-
filter: true,
|
28
|
-
search: true,
|
29
|
-
paginate:
|
30
|
-
pagesize: 20,
|
31
|
-
sortable: true,
|
32
|
-
batch_actions: false,
|
33
|
-
footer_content: false,
|
34
|
-
path: '#',
|
35
|
-
order_by: nil,
|
27
|
+
filter: true, # false for no filter row at all
|
28
|
+
search: true, # show fuzzy search field
|
29
|
+
paginate: Tabulatr.paginate, # true to show paginator
|
30
|
+
pagesize: 20, # default pagesize
|
31
|
+
sortable: true, # true to allow sorting (can be specified for every sortable column)
|
32
|
+
batch_actions: false, # :name => value hash of batch action stuff
|
33
|
+
footer_content: false, # if given, add a <%= content_for <footer_content> %> before the </table>
|
34
|
+
path: '#', # where to send the AJAX-requests to
|
35
|
+
order_by: nil, # default order
|
36
36
|
html_class: '',
|
37
37
|
pagination_position: :top,
|
38
38
|
counter_position: :top,
|
data/lib/tabulatr/version.rb
CHANGED
data/lib/tabulatr.rb
CHANGED
@@ -27,8 +27,10 @@ module Tabulatr
|
|
27
27
|
end
|
28
28
|
|
29
29
|
mattr_accessor :spinner
|
30
|
+
mattr_accessor :paginate
|
30
31
|
|
31
|
-
self.spinner
|
32
|
+
self.spinner = :standard
|
33
|
+
self.paginate = false
|
32
34
|
end
|
33
35
|
|
34
36
|
require 'tabulatr/engine'
|
@@ -64,4 +66,3 @@ end
|
|
64
66
|
Dir[File.join(File.dirname(__FILE__), "tabulatr", "renderer", "*.rb")].each do |file|
|
65
67
|
require file
|
66
68
|
end
|
67
|
-
|
@@ -20,7 +20,7 @@ Dummy::Application.configure do
|
|
20
20
|
# config.action_dispatch.rack_cache = true
|
21
21
|
|
22
22
|
# Disable Rails's static asset server (Apache or nginx will already do this).
|
23
|
-
config.
|
23
|
+
config.serve_static_files = false
|
24
24
|
|
25
25
|
# Compress JavaScripts and CSS.
|
26
26
|
config.assets.js_compressor = :uglifier
|
@@ -13,7 +13,7 @@ Dummy::Application.configure do
|
|
13
13
|
config.eager_load = false
|
14
14
|
|
15
15
|
# Configure static asset server for tests with Cache-Control for performance.
|
16
|
-
config.
|
16
|
+
config.serve_static_files = true
|
17
17
|
config.static_cache_control = "public, max-age=3600"
|
18
18
|
|
19
19
|
# Show full error reports and disable caching.
|
@@ -21,6 +21,7 @@ en:
|
|
21
21
|
'no': No
|
22
22
|
enum_filter:
|
23
23
|
none: ''
|
24
|
+
batch_confirm_text: This action will be applied to all rows within the current filter
|
24
25
|
de:
|
25
26
|
tabulatr:
|
26
27
|
rows_per_page: 'Ergebnisse pro Seite'
|
@@ -44,3 +45,4 @@ de:
|
|
44
45
|
'no': Nein
|
45
46
|
enum_filter:
|
46
47
|
none: ''
|
48
|
+
batch_confirm_text: Diese Aktion wird auf allen Datensätzen im aktuallen Filter ausgeführt
|
@@ -294,6 +294,18 @@ feature "Tabulatr" do
|
|
294
294
|
end
|
295
295
|
expect(page).to have_css(".tabulatr_table tbody tr", count: 1)
|
296
296
|
end
|
297
|
+
|
298
|
+
scenario 'executes the action for all items if nothing selected' do
|
299
|
+
product1 = Product.create!(:title => names[0], :active => true, :price => 10.0)
|
300
|
+
product2 = Product.create!(:title => names[1], :active => true, :price => 10.0)
|
301
|
+
product3 = Product.create!(:title => names[2], :active => false, :price => 10.0)
|
302
|
+
visit with_batch_actions_products_path
|
303
|
+
find('.tabulatr-batch-actions-menu-wrapper a').click
|
304
|
+
within('.dropdown.open') do
|
305
|
+
click_link 'Delete'
|
306
|
+
end
|
307
|
+
expect(page).to have_css('.tabulatr_table tbody tr', count: 0)
|
308
|
+
end
|
297
309
|
end
|
298
310
|
|
299
311
|
feature "Column options", js: true do
|
@@ -33,6 +33,20 @@ describe Tabulatr::Data do
|
|
33
33
|
expect(r[:products][:title]).to eql titles[ix]
|
34
34
|
end
|
35
35
|
end
|
36
|
+
|
37
|
+
it 'invokes the batch actions invoker with all ids if no row is selected' do
|
38
|
+
Product.create([{title: 'foo', price: 5, active: true}, {title: 'bar', price: 10, active: false}, {title: 'fuzz', price: 7, active: true}])
|
39
|
+
|
40
|
+
td = Tabulatr::Data.new(Product.where(active: true))
|
41
|
+
td.instance_variable_set(:@batch_actions, ->(batch_actions){
|
42
|
+
batch_actions.delete do |ids|
|
43
|
+
Product.where(id: ids).destroy_all
|
44
|
+
end
|
45
|
+
})
|
46
|
+
td.data_for_table(HashWithIndifferentAccess.new(example_params.merge(product_batch: 'delete', 'tabulatr_checked' => {'checked_ids' => ''})))
|
47
|
+
expect(Product.where(active: true).count).to be 0
|
48
|
+
expect(Product.count).to be 1
|
49
|
+
end
|
36
50
|
end
|
37
51
|
|
38
52
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tabulatr2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.9.
|
4
|
+
version: 0.9.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Peter Horn
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2015-
|
13
|
+
date: 2015-04-28 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rails
|
@@ -267,7 +267,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
267
267
|
version: '0'
|
268
268
|
requirements: []
|
269
269
|
rubyforge_project:
|
270
|
-
rubygems_version: 2.4.
|
270
|
+
rubygems_version: 2.4.6
|
271
271
|
signing_key:
|
272
272
|
specification_version: 4
|
273
273
|
summary: A tight DSL to build tables of ActiveRecord models with sorting, pagination,
|