effective_datatables 2.4.6 → 2.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +51 -0
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +23 -3
- data/app/assets/javascripts/effective_datatables/scopes.js.coffee +3 -0
- data/app/assets/javascripts/effective_datatables.js +1 -0
- data/app/assets/stylesheets/effective_datatables/_overrides.scss.erb +2 -1
- data/app/helpers/effective_datatables_helper.rb +11 -1
- data/app/models/effective/active_record_datatable_tool.rb +1 -1
- data/app/models/effective/array_datatable_tool.rb +4 -17
- data/app/models/effective/datatable.rb +42 -7
- data/app/models/effective/effective_datatable/dsl.rb +19 -1
- data/app/models/effective/effective_datatable/helpers.rb +24 -0
- data/app/models/effective/effective_datatable/options.rb +29 -2
- data/app/models/effective/effective_datatable/rendering.rb +24 -2
- data/app/views/effective/datatables/_datatable.html.haml +9 -1
- data/app/views/effective/datatables/_scopes.html.haml +15 -0
- data/lib/effective_datatables/version.rb +1 -1
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 698076a0613349e6b87650757f70464530e59933
|
4
|
+
data.tar.gz: 6ec43352f2160e31f382dcccfdc5091537f0fcdb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf5374370d10c21eda392ea2db88460eeb676de33a7e6e3f0236940955aa6a7399e14c3bbc52c902d390df5f3154b567a443819752b0ec4b8c19610964bd3aee
|
7
|
+
data.tar.gz: 0dfdf316d031c7d34c2e2fa0b338d1dde5560375fb14bc9e319129dcc77e2d7845ce3004c276e9f3527dd0f3c760ab05bf302cf362f56b295b7d3637aeed4169
|
data/README.md
CHANGED
@@ -537,6 +537,57 @@ resources :posts do
|
|
537
537
|
end
|
538
538
|
```
|
539
539
|
|
540
|
+
## scopes
|
541
|
+
|
542
|
+
When declaring a scope, a form field will automatically be placed above the datatable that can filter on the collection.
|
543
|
+
|
544
|
+
The value of the scope, its default value, will be available for use anywehre in your datatable via the `attributes` hash.
|
545
|
+
|
546
|
+
```ruby
|
547
|
+
scope :start_date, Time.zone.now-3.months, filter: { input_html: { class: 'datepicker' } }
|
548
|
+
```
|
549
|
+
|
550
|
+
and then in your collection, or any `table_column` block:
|
551
|
+
|
552
|
+
```ruby
|
553
|
+
def collection
|
554
|
+
Post.where('updated_at > ?', attributes[:start_date])
|
555
|
+
end
|
556
|
+
```
|
557
|
+
|
558
|
+
So initially, the `:start_date` will have the value of `Time.zone.now-3.months` and when submitted by the form, the value will be set there.
|
559
|
+
|
560
|
+
The form value will come back as a string, so you may need to `Time.zone.parse` that value.
|
561
|
+
|
562
|
+
Pass `scope :start_date, Time.zone.now-3.months, fallback: true` to fallback to the default value when the form submission is not present.
|
563
|
+
|
564
|
+
Any `filter: { ... }` options will be passed straight into simple_form.
|
565
|
+
|
566
|
+
## aggregates
|
567
|
+
|
568
|
+
Each `aggregate` directive adds an additional row to the table's tfoot.
|
569
|
+
|
570
|
+
This feature is intended to display a sum or average of all the table's currently displayed values.
|
571
|
+
|
572
|
+
```ruby
|
573
|
+
aggregate :average do |table_column, values, table_data|
|
574
|
+
if table_column[:name] == 'user'
|
575
|
+
'Average'
|
576
|
+
else
|
577
|
+
average = (values.sum { |value| convert_to_column_type(table_column, value) } / [values.length, 1].max)
|
578
|
+
content_tag(:span, number_to_percentage(average, precision: 0))
|
579
|
+
end
|
580
|
+
end
|
581
|
+
```
|
582
|
+
|
583
|
+
The above aggregate block will be called for each currently visible column in a datatable.
|
584
|
+
|
585
|
+
Here `table_column` is the table_column being rendered, `values` is an array of all the values in this one column. `table_data` is the whole transposed array of data.
|
586
|
+
|
587
|
+
The values will be whatever datatype each table_column returns.
|
588
|
+
|
589
|
+
It might be the case that the formatted values (strings) are returned, which is why `convert_to_column_type` is used above.
|
590
|
+
|
540
591
|
## table_columns
|
541
592
|
|
542
593
|
Quickly create multiple table_columns all with default options:
|
@@ -26,21 +26,21 @@ initializeDataTables = ->
|
|
26
26
|
exportOptions:
|
27
27
|
format:
|
28
28
|
header: (str) -> $("<div>#{str}</div>").children('.filter-label').first().text()
|
29
|
-
columns: ':
|
29
|
+
columns: ':not(.col-actions)'
|
30
30
|
},
|
31
31
|
{
|
32
32
|
extend: 'csv',
|
33
33
|
exportOptions:
|
34
34
|
format:
|
35
35
|
header: (str) -> $("<div>#{str}</div>").children('.filter-label').first().text()
|
36
|
-
columns: ':
|
36
|
+
columns: ':not(.col-actions)'
|
37
37
|
},
|
38
38
|
{
|
39
39
|
extend: 'excel',
|
40
40
|
exportOptions:
|
41
41
|
format:
|
42
42
|
header: (str) -> $("<div>#{str}</div>").children('.filter-label').first().text()
|
43
|
-
columns: ':
|
43
|
+
columns: ':not(.col-actions)'
|
44
44
|
},
|
45
45
|
{
|
46
46
|
extend: 'print',
|
@@ -69,12 +69,16 @@ initializeDataTables = ->
|
|
69
69
|
pagingType: 'simple_numbers'
|
70
70
|
initComplete: (settings) ->
|
71
71
|
initializeBulkActions(this.api())
|
72
|
+
initializeScopes(this.api())
|
72
73
|
initializeFilters(this.api())
|
73
74
|
drawCallback: (settings) ->
|
74
75
|
$table = $(this.api().table().node())
|
75
76
|
selected = $table.data('bulk-actions-restore-selected-values')
|
76
77
|
completeBulkAction($table, selected) if selected && selected.length > 0
|
77
78
|
|
79
|
+
if settings['json'] && settings['json']['aggregates']
|
80
|
+
drawAggregates($table, settings['json']['aggregates'])
|
81
|
+
|
78
82
|
# Copies the bulk actions html, stored in a data attribute on the table, into the buttons area
|
79
83
|
initializeBulkActions = (api) ->
|
80
84
|
$table = $(api.table().node())
|
@@ -94,6 +98,22 @@ initializeDataTables = ->
|
|
94
98
|
$wrapper.children().first().find('.buttons-bulk-actions').children('button').removeAttr('disabled')
|
95
99
|
$table.siblings('.dataTables_processing').html('Processing...')
|
96
100
|
|
101
|
+
drawAggregates = ($table, aggregates) ->
|
102
|
+
$tfoot = $table.find('tfoot').first()
|
103
|
+
|
104
|
+
$.each aggregates, (row, values) =>
|
105
|
+
$row = $tfoot.children().eq(row)
|
106
|
+
|
107
|
+
if $row
|
108
|
+
$.each values, (col, value) => $row.children().eq(col).html(value)
|
109
|
+
|
110
|
+
# Appends the scope html
|
111
|
+
initializeScopes = (api) ->
|
112
|
+
$table = $(api.table().node())
|
113
|
+
scopes = $table.data('scopes')
|
114
|
+
|
115
|
+
$table.closest('.dataTables_wrapper').prepend(scopes['scopeHtml']) if scopes
|
116
|
+
|
97
117
|
# Appends the filter html, stored in the column definitions, into each column header
|
98
118
|
initializeFilters = (api) ->
|
99
119
|
api.columns().flatten().each (index) =>
|
@@ -49,7 +49,8 @@ table.dataTable.sort-hidden thead .sorting_desc { background-image: none; }
|
|
49
49
|
|
50
50
|
// Filter bar
|
51
51
|
table.dataTable .form-group { width: 100%; margin-left: 0px; margin-right: 0px; }
|
52
|
-
table.dataTable input
|
52
|
+
table.dataTable input { width: 100%; }
|
53
|
+
table.dataTable select { width: 100%; }
|
53
54
|
table.dataTable .form-control { width: 100%; }
|
54
55
|
table.dataTable .form-group.datatable_filter_bulk_actions { margin-left: 4px; }
|
55
56
|
|
@@ -51,6 +51,17 @@ module EffectiveDatatablesHelper
|
|
51
51
|
}.to_json()
|
52
52
|
end
|
53
53
|
|
54
|
+
def datatable_scopes(datatable)
|
55
|
+
return false unless datatable.scopes.present?
|
56
|
+
|
57
|
+
{
|
58
|
+
scopeHtml: render(
|
59
|
+
partial: 'effective/datatables/scopes',
|
60
|
+
locals: HashWithIndifferentAccess.new(datatable: datatable)
|
61
|
+
)
|
62
|
+
}.to_json()
|
63
|
+
end
|
64
|
+
|
54
65
|
def datatable_header_filter(form, name, value, opts)
|
55
66
|
return render(partial: opts[:header_partial], locals: {form: form, name: (opts[:label] || name), column: opts}) if opts[:header_partial].present?
|
56
67
|
|
@@ -119,7 +130,6 @@ module EffectiveDatatablesHelper
|
|
119
130
|
attributes[:active_admin_path] rescue false
|
120
131
|
end
|
121
132
|
|
122
|
-
|
123
133
|
### Bulk Actions DSL Methods
|
124
134
|
def bulk_action(*args)
|
125
135
|
content_for(:effective_datatables_bulk_actions) { content_tag(:li, link_to(*args)) }
|
@@ -211,7 +211,7 @@ module Effective
|
|
211
211
|
when :price
|
212
212
|
price_in_cents = (term.gsub(/[^0-9|\.]/, '').to_f * 100.0).to_i
|
213
213
|
collection.public_send(sql_op, "#{sql_column} = :term", term: price_in_cents)
|
214
|
-
when :currency, :decimal, :number
|
214
|
+
when :currency, :decimal, :number, :percentage
|
215
215
|
collection.public_send(sql_op, "#{sql_column} = :term", term: term.gsub(/[^0-9|\.]/, '').to_f)
|
216
216
|
else
|
217
217
|
collection.public_send(sql_op, "#{sql_column} = :term", term: term)
|
@@ -3,7 +3,7 @@ module Effective
|
|
3
3
|
class ArrayDatatableTool
|
4
4
|
attr_accessor :table_columns
|
5
5
|
|
6
|
-
delegate :page, :per_page, :search_column, :order_column, :display_table_columns, :to => :@datatable
|
6
|
+
delegate :page, :per_page, :search_column, :order_column, :display_table_columns, :convert_to_column_type, :to => :@datatable
|
7
7
|
|
8
8
|
def initialize(datatable, table_columns)
|
9
9
|
@datatable = datatable
|
@@ -30,7 +30,7 @@ module Effective
|
|
30
30
|
if direction == :asc
|
31
31
|
collection.sort! do |x, y|
|
32
32
|
if (x[index] && y[index])
|
33
|
-
|
33
|
+
convert_to_column_type(table_column, x[index]) <=> convert_to_column_type(table_column, y[index])
|
34
34
|
elsif x[index]
|
35
35
|
-1
|
36
36
|
elsif y[index]
|
@@ -42,7 +42,7 @@ module Effective
|
|
42
42
|
else
|
43
43
|
collection.sort! do |x, y|
|
44
44
|
if (x[index] && y[index])
|
45
|
-
|
45
|
+
convert_to_column_type(table_column, y[index]) <=> convert_to_column_type(table_column, x[index])
|
46
46
|
elsif x[index]
|
47
47
|
1
|
48
48
|
elsif y[index]
|
@@ -70,7 +70,7 @@ module Effective
|
|
70
70
|
|
71
71
|
collection.select! do |row|
|
72
72
|
if table_column[:filter][:fuzzy]
|
73
|
-
row[index].to_s.downcase.include?(search_term)
|
73
|
+
convert_to_column_type(table_column, row[index]).to_s.downcase.include?(search_term)
|
74
74
|
else
|
75
75
|
row[index] == search_term
|
76
76
|
end
|
@@ -87,19 +87,6 @@ module Effective
|
|
87
87
|
display_table_columns.present? ? display_table_columns.keys.index(column[:name]) : column[:array_index]
|
88
88
|
end
|
89
89
|
|
90
|
-
# When we order by Array, it's already a string.
|
91
|
-
# This gives us a mechanism to sort numbers as numbers
|
92
|
-
def cast_array_column_value(table_column, value)
|
93
|
-
case table_column[:type]
|
94
|
-
when :number, :price, :decimal, :float
|
95
|
-
(value.to_s.gsub(/[^0-9|\.]/, '').to_f rescue 0.00)
|
96
|
-
when :integer
|
97
|
-
(value.to_s.gsub(/\D/, '').to_i rescue 0)
|
98
|
-
else
|
99
|
-
value
|
100
|
-
end
|
101
|
-
end
|
102
|
-
|
103
90
|
end
|
104
91
|
end
|
105
92
|
|
@@ -11,6 +11,7 @@ module Effective
|
|
11
11
|
extend Effective::EffectiveDatatable::Dsl::ClassMethods
|
12
12
|
|
13
13
|
include Effective::EffectiveDatatable::Ajax
|
14
|
+
include Effective::EffectiveDatatable::Helpers
|
14
15
|
include Effective::EffectiveDatatable::Hooks
|
15
16
|
include Effective::EffectiveDatatable::Options
|
16
17
|
include Effective::EffectiveDatatable::Rendering
|
@@ -23,6 +24,7 @@ module Effective
|
|
23
24
|
|
24
25
|
initialize_datatable # This creates @table_columns based on the DSL datatable do .. end block
|
25
26
|
initialize_options # This normalizes all the options
|
27
|
+
initialize_scopes # This normalizes scopes, and copies scopes to attributes
|
26
28
|
|
27
29
|
unless active_record_collection? || array_collection?
|
28
30
|
raise "Unsupported collection type. Should be ActiveRecord class, ActiveRecord relation, or an Array of Arrays [[1, 'something'], [2, 'something else']]"
|
@@ -37,9 +39,17 @@ module Effective
|
|
37
39
|
@table_columns
|
38
40
|
end
|
39
41
|
|
42
|
+
def scopes
|
43
|
+
@scopes
|
44
|
+
end
|
45
|
+
|
46
|
+
def aggregates
|
47
|
+
@aggregates
|
48
|
+
end
|
49
|
+
|
40
50
|
# Any attributes set on initialize will be echoed back and available to the class
|
41
51
|
def attributes
|
42
|
-
@attributes ||= HashWithIndifferentAccess.new
|
52
|
+
@attributes ||= HashWithIndifferentAccess.new
|
43
53
|
end
|
44
54
|
|
45
55
|
def to_key; []; end # Searching & Filters
|
@@ -68,12 +78,17 @@ module Effective
|
|
68
78
|
def to_json
|
69
79
|
raise 'Effective::Datatable to_json called with a nil view. Please call render_datatable(@datatable) or @datatable.view = view before this method' unless view.present?
|
70
80
|
|
71
|
-
@json ||=
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
81
|
+
@json ||= begin
|
82
|
+
data = table_data
|
83
|
+
|
84
|
+
{
|
85
|
+
:draw => (params[:draw] || 0),
|
86
|
+
:data => (data || []),
|
87
|
+
:recordsTotal => (total_records || 0),
|
88
|
+
:recordsFiltered => (display_records || 0),
|
89
|
+
:aggregates => (aggregate_data(data) || [])
|
90
|
+
}
|
91
|
+
end
|
77
92
|
end
|
78
93
|
|
79
94
|
def present?
|
@@ -104,6 +119,22 @@ module Effective
|
|
104
119
|
@view = view_context
|
105
120
|
@view.formats = [:html]
|
106
121
|
|
122
|
+
# Set any scopes
|
123
|
+
if @view.params[:scopes].kind_of?(Hash)
|
124
|
+
@view.params[:scopes].each do |name, value|
|
125
|
+
next unless scopes.key?(name)
|
126
|
+
|
127
|
+
if scopes[name][:fallback] || scopes[name][:presence]
|
128
|
+
value = value.presence || scopes[name][:default]
|
129
|
+
end
|
130
|
+
|
131
|
+
self.attributes[name] = value
|
132
|
+
|
133
|
+
self.scopes[name][:filter][:input_html] ||= HashWithIndifferentAccess.new
|
134
|
+
self.scopes[name][:filter][:input_html][:value] = value
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
107
138
|
# 'Just work' with attributes
|
108
139
|
@view.class.send(:attr_accessor, :attributes)
|
109
140
|
@view.attributes = self.attributes
|
@@ -116,6 +147,10 @@ module Effective
|
|
116
147
|
@view.class_eval { delegate view_method, :to => :@effective_datatable }
|
117
148
|
end
|
118
149
|
|
150
|
+
Effective::EffectiveDatatable::Helpers.instance_methods(false).each do |helper_method|
|
151
|
+
@view.class_eval { delegate helper_method, :to => :@effective_datatable }
|
152
|
+
end
|
153
|
+
|
119
154
|
# Clear the search_terms memoization
|
120
155
|
@search_terms = nil
|
121
156
|
@order_name = nil
|
@@ -27,7 +27,7 @@ module Effective
|
|
27
27
|
end
|
28
28
|
raise "You cannot use both partial: ... and proc: ..." if options[:partial] && options[:proc]
|
29
29
|
|
30
|
-
(@table_columns ||= HashWithIndifferentAccess.new
|
30
|
+
(@table_columns ||= HashWithIndifferentAccess.new)[name] = options
|
31
31
|
end
|
32
32
|
|
33
33
|
def array_column(name, options = {}, proc = nil, &block)
|
@@ -72,6 +72,24 @@ module Effective
|
|
72
72
|
table_column(name, opts, proc)
|
73
73
|
end
|
74
74
|
|
75
|
+
def scope(name, default, options = {}, &block)
|
76
|
+
if block_given?
|
77
|
+
raise "You cannot use partial: ... with the block syntax" if options[:partial]
|
78
|
+
options[:block] = block
|
79
|
+
end
|
80
|
+
|
81
|
+
(@scopes ||= HashWithIndifferentAccess.new)[name] = options.merge(default: default)
|
82
|
+
end
|
83
|
+
|
84
|
+
def aggregate(name, options = {}, &block)
|
85
|
+
if block_given?
|
86
|
+
raise "You cannot use proc: ... with the block syntax" if options[:proc]
|
87
|
+
options[:block] = block
|
88
|
+
end
|
89
|
+
|
90
|
+
(@aggregates ||= HashWithIndifferentAccess.new)[name] = options
|
91
|
+
end
|
92
|
+
|
75
93
|
end
|
76
94
|
end
|
77
95
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Effective
|
2
|
+
module EffectiveDatatable
|
3
|
+
module Helpers
|
4
|
+
|
5
|
+
# When we order by Array, it's already a string.
|
6
|
+
# This gives us a mechanism to sort numbers as numbers
|
7
|
+
def convert_to_column_type(table_column, value)
|
8
|
+
if value.html_safe? && value.kind_of?(String) && value.start_with?('<')
|
9
|
+
value = ActionView::Base.full_sanitizer.sanitize(value)
|
10
|
+
end
|
11
|
+
|
12
|
+
case table_column[:type]
|
13
|
+
when :number, :price, :decimal, :float, :percentage
|
14
|
+
(value.to_s.gsub(/[^0-9|\.]/, '').to_f rescue 0.00) unless value.kind_of?(Numeric)
|
15
|
+
when :integer
|
16
|
+
(value.to_s.gsub(/\D/, '').to_i rescue 0) unless value.kind_of?(Integer)
|
17
|
+
else
|
18
|
+
; # Do nothing
|
19
|
+
end || value
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -8,12 +8,36 @@ module Effective
|
|
8
8
|
@table_columns = initialize_column_options(@table_columns)
|
9
9
|
end
|
10
10
|
|
11
|
+
def initialize_scopes
|
12
|
+
@scopes = initialize_scope_options(@scopes)
|
13
|
+
end
|
14
|
+
|
11
15
|
def quote_sql(name)
|
12
16
|
collection_class.connection.quote_column_name(name) rescue name
|
13
17
|
end
|
14
18
|
|
15
19
|
protected
|
16
20
|
|
21
|
+
# The scope DSL is
|
22
|
+
# scope :start_date, default_value, options {}
|
23
|
+
|
24
|
+
# A scope comes to us like {:start_date => {default: Time.zone.now, filter: {as: :select, collection: ... input_html :}}}
|
25
|
+
# We want to make sure an input_html: { value: default } exists
|
26
|
+
def initialize_scope_options(scopes)
|
27
|
+
(scopes || []).each do |name, options|
|
28
|
+
options[:filter] ||= HashWithIndifferentAccess.new()
|
29
|
+
options[:filter][:input_html] ||= HashWithIndifferentAccess.new()
|
30
|
+
options[:filter][:input_html][:value] = options[:default]
|
31
|
+
end
|
32
|
+
|
33
|
+
# For each scope, copy it into the attributes, so we can get at the value
|
34
|
+
(scopes || []).each do |name, options|
|
35
|
+
self.attributes[name] ||= options[:default]
|
36
|
+
end
|
37
|
+
|
38
|
+
scopes
|
39
|
+
end
|
40
|
+
|
17
41
|
def initialize_column_options(cols)
|
18
42
|
sql_table = (collection.table rescue nil)
|
19
43
|
|
@@ -81,8 +105,6 @@ module Effective
|
|
81
105
|
:bulk_actions_column
|
82
106
|
elsif name.include?('_address') && (collection_class.new rescue nil).respond_to?(:effective_addresses)
|
83
107
|
:effective_address
|
84
|
-
elsif name == 'id' || name.include?('year') || name.include?('_id')
|
85
|
-
:non_formatted_integer
|
86
108
|
elsif sql_column.try(:type).present?
|
87
109
|
sql_column.type
|
88
110
|
else
|
@@ -92,6 +114,11 @@ module Effective
|
|
92
114
|
|
93
115
|
cols[name][:class] = "col-#{cols[name][:type]} col-#{name} #{cols[name][:class]}".strip
|
94
116
|
|
117
|
+
# Formats
|
118
|
+
if name == 'id' || name.include?('year') || name.include?('_id')
|
119
|
+
cols[name][:format] = :non_formatted_integer
|
120
|
+
end
|
121
|
+
|
95
122
|
# We can't really sort a HasMany or EffectiveAddress field
|
96
123
|
if [:has_many, :effective_address].include?(cols[name][:type])
|
97
124
|
cols[name][:sortable] = false
|
@@ -137,7 +137,7 @@ module Effective
|
|
137
137
|
obj.send(name)
|
138
138
|
end
|
139
139
|
rescue => e
|
140
|
-
obj.try(:[], name)
|
140
|
+
Rails.env.production? ? obj.try(:[], name) : raise(e)
|
141
141
|
end
|
142
142
|
end
|
143
143
|
end
|
@@ -154,7 +154,7 @@ module Effective
|
|
154
154
|
row[index] = value.to_s
|
155
155
|
end
|
156
156
|
|
157
|
-
case opts[:type]
|
157
|
+
case (opts[:format] || opts[:type])
|
158
158
|
when :belongs_to, :belongs_to_polymorphic
|
159
159
|
row[index] = value.to_s
|
160
160
|
when :has_many
|
@@ -183,6 +183,8 @@ module Effective
|
|
183
183
|
row[index] = number_to_currency(value / 100.0)
|
184
184
|
when :currency
|
185
185
|
row[index] = number_to_currency(value || 0)
|
186
|
+
when :percentage
|
187
|
+
row[index] = number_to_percentage(value || 0)
|
186
188
|
when :integer
|
187
189
|
if EffectiveDatatables.integer_format.kind_of?(Symbol)
|
188
190
|
row[index] = view.instance_exec { public_send(EffectiveDatatables.integer_format, value) }
|
@@ -206,6 +208,26 @@ module Effective
|
|
206
208
|
collection
|
207
209
|
end
|
208
210
|
|
211
|
+
# This should return an Array of values the same length as table_data
|
212
|
+
def aggregate_data(table_data)
|
213
|
+
return false unless aggregates.present?
|
214
|
+
|
215
|
+
values = table_data.transpose
|
216
|
+
|
217
|
+
aggregates.map do |name, options|
|
218
|
+
(display_table_columns || table_columns).map.with_index do |(name, column), index|
|
219
|
+
|
220
|
+
if column[:visible] != true
|
221
|
+
''
|
222
|
+
elsif (options[:block] || options[:proc]).respond_to?(:call)
|
223
|
+
view.instance_exec(column, (values[index] || []), values, &(options[:block] || options[:proc]))
|
224
|
+
else
|
225
|
+
''
|
226
|
+
end
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
209
231
|
private
|
210
232
|
|
211
233
|
def controller_namespace
|
@@ -7,6 +7,7 @@
|
|
7
7
|
'bulk-actions' => datatable_bulk_actions(datatable),
|
8
8
|
'columns' => datatable_columns(datatable),
|
9
9
|
'input-js-options' => local_assigns[:input_js_options],
|
10
|
+
'scopes' => datatable_scopes(datatable),
|
10
11
|
'simple' => datatable.simple?.to_s,
|
11
12
|
'source' => effective_datatables.datatable_path(datatable, {format: 'json'}.merge(attributes: datatable.attributes)).chomp('?'),
|
12
13
|
'default-order' => datatable_default_order(datatable),
|
@@ -23,7 +24,14 @@
|
|
23
24
|
%th= opts[:label] || name
|
24
25
|
|
25
26
|
%tbody
|
26
|
-
-
|
27
|
+
- datatable.to_json[:data].each do |row|
|
27
28
|
%tr
|
28
29
|
- row.each do |col|
|
29
30
|
%td= col.to_s.html_safe
|
31
|
+
|
32
|
+
- if datatable.aggregates.present?
|
33
|
+
%tfoot
|
34
|
+
- datatable.to_json[:aggregates].each do |row|
|
35
|
+
%tr
|
36
|
+
- row.each do |col|
|
37
|
+
%td= col.to_s.html_safe
|
@@ -0,0 +1,15 @@
|
|
1
|
+
.row
|
2
|
+
.col-sm-12
|
3
|
+
= simple_form_for :scopes, url: request.path, method: :get, html: { class: 'form-inline' } do |form|
|
4
|
+
|
5
|
+
- datatable.scopes.each do |name, options|
|
6
|
+
- if options[:block].present?
|
7
|
+
= form.instance_exec(form, &options[:block])
|
8
|
+
- elsif options[:partial].present?
|
9
|
+
= render partial: options[:partial], locals: { form: form, f: form, datatable: datatable }
|
10
|
+
- else
|
11
|
+
= form.input name, options[:filter]
|
12
|
+
|
13
|
+
= form.submit 'Refresh', class: 'btn btn-primary', 'data-disable-with' => 'Refreshing...'
|
14
|
+
= link_to 'Reset', '#', 'data-reset-form' => true
|
15
|
+
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_datatables
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-06-
|
11
|
+
date: 2016-06-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -123,6 +123,7 @@ files:
|
|
123
123
|
- app/assets/javascripts/effective_datatables/bulk_actions.js.coffee
|
124
124
|
- app/assets/javascripts/effective_datatables/initialize.js.coffee
|
125
125
|
- app/assets/javascripts/effective_datatables/responsive.js.coffee
|
126
|
+
- app/assets/javascripts/effective_datatables/scopes.js.coffee
|
126
127
|
- app/assets/javascripts/vendor/jquery.debounce.min.js
|
127
128
|
- app/assets/javascripts/vendor/jszip.min.js
|
128
129
|
- app/assets/stylesheets/dataTables/buttons/buttons.bootstrap.min.css
|
@@ -143,6 +144,7 @@ files:
|
|
143
144
|
- app/models/effective/datatable.rb
|
144
145
|
- app/models/effective/effective_datatable/ajax.rb
|
145
146
|
- app/models/effective/effective_datatable/dsl.rb
|
147
|
+
- app/models/effective/effective_datatable/helpers.rb
|
146
148
|
- app/models/effective/effective_datatable/hooks.rb
|
147
149
|
- app/models/effective/effective_datatable/options.rb
|
148
150
|
- app/models/effective/effective_datatable/rendering.rb
|
@@ -150,6 +152,7 @@ files:
|
|
150
152
|
- app/views/effective/datatables/_bulk_actions_column.html.haml
|
151
153
|
- app/views/effective/datatables/_bulk_actions_dropdown.html.haml
|
152
154
|
- app/views/effective/datatables/_datatable.html.haml
|
155
|
+
- app/views/effective/datatables/_scopes.html.haml
|
153
156
|
- app/views/effective/datatables/_spacer_template.html
|
154
157
|
- config/routes.rb
|
155
158
|
- lib/effective_datatables.rb
|