effective_datatables 2.4.6 → 2.5.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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
|