effective_datatables 2.9.0 → 2.10.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 +10 -4
- data/app/assets/javascripts/effective_datatables.js +2 -1
- data/app/assets/javascripts/effective_datatables/bulk_actions.js.coffee +16 -0
- data/app/assets/javascripts/effective_datatables/events.js.coffee +13 -0
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +3 -26
- data/app/controllers/effective/datatables_controller.rb +10 -13
- data/app/helpers/effective_datatables_helper.rb +4 -4
- data/app/helpers/effective_datatables_private_helper.rb +7 -0
- data/app/models/effective/array_datatable_tool.rb +1 -1
- data/app/models/effective/datatable.rb +8 -7
- data/app/models/effective/effective_datatable/hooks.rb +6 -6
- data/app/models/effective/effective_datatable/options.rb +1 -28
- data/app/models/effective/effective_datatable/rendering.rb +3 -3
- data/lib/effective_datatables/version.rb +1 -1
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 38df969bd8b6fe71d4e850119c2b65d8b961b858
|
4
|
+
data.tar.gz: b89352ad871da29903b18d0f1693740edce96141
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1395f9861d1a4c806b3b1e21d618c6782e926d5f3e865d4e3060d99b7b0c56ae022afe50ab5381d940b196b51ec73c131104b1b92d2f5ffe7cbc353715fcefd8
|
7
|
+
data.tar.gz: 0bc0b48bbfd87c9e09b09520e19b27b68608230f07f7baaad76eb9f446f83d158554f388d4c96b1b3488c035e2671dac3a498768693cc134263dbe4e2bf5997e
|
data/README.md
CHANGED
@@ -487,10 +487,15 @@ You can define any number of `bulk_action`s, and separate them with one or more
|
|
487
487
|
The `bulk_action` method is just an alias for `link_to`, so all the same options will work.
|
488
488
|
|
489
489
|
```ruby
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
490
|
+
datatable do
|
491
|
+
bulk_actions_column do
|
492
|
+
bulk_action 'Approve all', bulk_approve_posts_path, data: {confirm: 'Approve all selected posts?'}
|
493
|
+
bulk_action_divider
|
494
|
+
bulk_action 'Send emails', bulk_email_posts_path, data : {confirm: 'Really send emails?'}
|
495
|
+
end
|
496
|
+
|
497
|
+
...
|
498
|
+
|
494
499
|
end
|
495
500
|
```
|
496
501
|
|
@@ -504,6 +509,7 @@ class PostsController < ApplicationController
|
|
504
509
|
# You should probably write this inside a transaction. This is just an example.
|
505
510
|
begin
|
506
511
|
@posts.each { |post| post.approve! }
|
512
|
+
render json: { status: 200, message: "Successfully approved #{@posts.length} posts." }
|
507
513
|
rescue => e
|
508
514
|
render json: { status: 500, message: 'An error occured while approving a post.' }
|
509
515
|
end
|
@@ -15,8 +15,9 @@
|
|
15
15
|
//= require dataTables/responsive/responsive.bootstrap
|
16
16
|
|
17
17
|
//= require effective_datatables/bulk_actions
|
18
|
+
//= require effective_datatables/events
|
18
19
|
//= require effective_datatables/responsive
|
19
20
|
//= require effective_datatables/scopes
|
20
|
-
//= require effective_datatables/charts
|
21
21
|
|
22
|
+
//= require effective_datatables/charts
|
22
23
|
//= require effective_datatables/initialize
|
@@ -79,3 +79,19 @@ $(document).on 'click', '.buttons-bulk-actions a', (event) ->
|
|
79
79
|
$table.dataTable().data('bulk-actions-restore-selected-values', values)
|
80
80
|
$table.DataTable().draw()
|
81
81
|
)
|
82
|
+
|
83
|
+
# We borrow the Processing div for our bulk action success/error messages
|
84
|
+
# This makes sure that the message is displayed for 1500ms
|
85
|
+
$(document).on 'processing.dt', (event, settings, visible) ->
|
86
|
+
return if settings.bDestroying
|
87
|
+
|
88
|
+
$processing = $(event.target).siblings('.dataTables_processing').first()
|
89
|
+
return unless $processing.data('bulk-actions-processing')
|
90
|
+
|
91
|
+
timeout = $processing.show().data('timeout')
|
92
|
+
clearTimeout(timeout) if timeout
|
93
|
+
$processing.data('timeout', setTimeout( =>
|
94
|
+
$processing.html('Processing...').hide()
|
95
|
+
$processing.data('bulk-actions-processing', null)
|
96
|
+
, 1500)
|
97
|
+
)
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# Redraw the table, and initialize any filter form inputs after the last column made visible
|
2
|
+
$(document).on 'column-visibility.dt', (event, settings, index, state) ->
|
3
|
+
return if settings.bDestroying
|
4
|
+
|
5
|
+
$table = $(event.target)
|
6
|
+
|
7
|
+
timeout = $table.data('timeout')
|
8
|
+
clearTimeout(timeout) if timeout
|
9
|
+
$table.data('timeout', setTimeout( =>
|
10
|
+
$table.DataTable().draw()
|
11
|
+
$.event.trigger('page:change')
|
12
|
+
, 700)
|
13
|
+
)
|
@@ -169,38 +169,15 @@ initializeDataTables = ->
|
|
169
169
|
if datatable.data('effective-form-inputs')
|
170
170
|
try table.closest('.dataTables_wrapper').find('.dataTables_length select').select2()
|
171
171
|
|
172
|
-
# Capture column visibility changes and refresh datatable
|
173
|
-
datatable.on 'column-visibility.dt', (event, settings, index, state) ->
|
174
|
-
$table = $(event.currentTarget)
|
175
|
-
|
176
|
-
timeout = $table.data('timeout')
|
177
|
-
clearTimeout(timeout) if timeout
|
178
|
-
$table.data('timeout', setTimeout( =>
|
179
|
-
$table.DataTable().draw()
|
180
|
-
$.event.trigger('page:change')
|
181
|
-
, 700)
|
182
|
-
)
|
183
|
-
|
184
|
-
# We borrow the Processing div for our bulk action success/error messages
|
185
|
-
# This makes sure that the message is displayed for 1500ms
|
186
|
-
datatable.on 'processing.dt', (event, settings, visible) ->
|
187
|
-
$processing = $(event.currentTarget).siblings('.dataTables_processing').first()
|
188
|
-
return unless $processing.data('bulk-actions-processing')
|
189
|
-
|
190
|
-
timeout = $processing.show().data('timeout')
|
191
|
-
clearTimeout(timeout) if timeout
|
192
|
-
$processing.data('timeout', setTimeout( =>
|
193
|
-
$processing.html('Processing...').hide()
|
194
|
-
$processing.data('bulk-actions-processing', null)
|
195
|
-
, 1500)
|
196
|
-
)
|
197
|
-
|
198
172
|
destroyDataTables = ->
|
199
173
|
$('table.effective-datatable').each ->
|
200
174
|
if $.fn.DataTable.fnIsDataTable(this)
|
201
175
|
$(this).DataTable().destroy()
|
202
176
|
|
177
|
+
$ -> initializeDataTables()
|
203
178
|
$(document).on 'page:change', -> initializeDataTables()
|
204
179
|
$(document).on 'turbolinks:load', -> initializeDataTables()
|
180
|
+
$(document).on 'turbolinks:before-cache', -> destroyDataTables()
|
181
|
+
|
205
182
|
|
206
183
|
|
@@ -10,15 +10,15 @@ module Effective
|
|
10
10
|
@datatable = find_datatable(params[:id]).try(:new, attributes.merge(scopes))
|
11
11
|
@datatable.view = view_context if !@datatable.nil?
|
12
12
|
|
13
|
-
EffectiveDatatables.authorized?(self, :index, @datatable.try(:collection_class)
|
13
|
+
EffectiveDatatables.authorized?(self, :index, @datatable.try(:collection_class))
|
14
14
|
|
15
15
|
respond_to do |format|
|
16
16
|
format.html
|
17
17
|
format.json {
|
18
18
|
if Rails.env.production?
|
19
|
-
render :
|
19
|
+
render json: (@datatable.to_json rescue error_json)
|
20
20
|
else
|
21
|
-
render :
|
21
|
+
render json: @datatable.to_json
|
22
22
|
end
|
23
23
|
}
|
24
24
|
end
|
@@ -28,20 +28,17 @@ module Effective
|
|
28
28
|
private
|
29
29
|
|
30
30
|
def find_datatable(id)
|
31
|
-
|
32
|
-
klass = "effective/datatables/#{id}".classify
|
33
|
-
|
34
|
-
(id_plural ? klass.pluralize : klass).safe_constantize
|
31
|
+
id.classify.safe_constantize || id.classify.pluralize.safe_constantize
|
35
32
|
end
|
36
33
|
|
37
34
|
def error_json
|
38
35
|
{
|
39
|
-
:
|
40
|
-
:
|
41
|
-
:
|
42
|
-
:
|
43
|
-
:
|
44
|
-
:
|
36
|
+
draw: params[:draw].to_i,
|
37
|
+
data: [],
|
38
|
+
recordsTotal: 0,
|
39
|
+
recordsFiltered: 0,
|
40
|
+
aggregates: [],
|
41
|
+
charts: {}
|
45
42
|
}.to_json
|
46
43
|
end
|
47
44
|
|
@@ -7,9 +7,9 @@ module EffectiveDatatablesHelper
|
|
7
7
|
datatable.view ||= self
|
8
8
|
|
9
9
|
begin
|
10
|
-
EffectiveDatatables.authorized?(controller, :index, datatable.
|
10
|
+
EffectiveDatatables.authorized?(controller, :index, datatable.collection_class) || raise('unauthorized')
|
11
11
|
rescue => e
|
12
|
-
return content_tag(:p, "You are not authorized to view this datatable. (cannot :index, #{datatable.
|
12
|
+
return content_tag(:p, "You are not authorized to view this datatable. (cannot :index, #{datatable.collection_class})")
|
13
13
|
end
|
14
14
|
|
15
15
|
render partial: 'effective/datatables/datatable',
|
@@ -23,9 +23,9 @@ module EffectiveDatatablesHelper
|
|
23
23
|
datatable.simple = true
|
24
24
|
|
25
25
|
begin
|
26
|
-
EffectiveDatatables.authorized?(controller, :index, datatable.
|
26
|
+
EffectiveDatatables.authorized?(controller, :index, datatable.collection_class) || raise('unauthorized')
|
27
27
|
rescue => e
|
28
|
-
return content_tag(:p, "You are not authorized to view this datatable. (cannot :index, #{datatable.
|
28
|
+
return content_tag(:p, "You are not authorized to view this datatable. (cannot :index, #{datatable.collection_class})})")
|
29
29
|
end
|
30
30
|
|
31
31
|
render partial: 'effective/datatables/datatable',
|
@@ -45,12 +45,14 @@ module EffectiveDatatablesPrivateHelper
|
|
45
45
|
pattern = opts[:filter].key?(:pattern) ? opts[:filter][:pattern] : nil
|
46
46
|
placeholder = opts[:filter].key?(:placeholder) ? opts[:filter][:placeholder] : (opts[:label] || name.titleize)
|
47
47
|
title = opts[:filter].key?(:title) ? opts[:filter][:title] : (opts[:label] || name.titleize)
|
48
|
+
wrapper_html = { class: 'datatable_filter' }
|
48
49
|
|
49
50
|
case opts[:filter][:as]
|
50
51
|
when :string, :text, :number
|
51
52
|
form.input name, label: false, required: false, value: value,
|
52
53
|
as: :string,
|
53
54
|
placeholder: placeholder,
|
55
|
+
wrapper_html: wrapper_html,
|
54
56
|
input_html: { name: nil, value: value, title: title, pattern: pattern, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} }
|
55
57
|
when :obfuscated_id
|
56
58
|
pattern ||= '[0-9]{3}-?[0-9]{4}-?[0-9]{3}'
|
@@ -59,11 +61,13 @@ module EffectiveDatatablesPrivateHelper
|
|
59
61
|
form.input name, label: false, required: false, value: value,
|
60
62
|
as: :string,
|
61
63
|
placeholder: placeholder,
|
64
|
+
wrapper_html: wrapper_html,
|
62
65
|
input_html: { name: nil, value: value, title: title, pattern: pattern, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} }
|
63
66
|
when :date
|
64
67
|
form.input name, label: false, required: false, value: value,
|
65
68
|
as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_date_picker) ? :effective_date_picker : :string),
|
66
69
|
placeholder: placeholder,
|
70
|
+
wrapper_html: wrapper_html,
|
67
71
|
input_group: false,
|
68
72
|
input_html: { name: nil, value: value, title: title, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} },
|
69
73
|
input_js: { useStrict: true, keepInvalid: true }
|
@@ -71,6 +75,7 @@ module EffectiveDatatablesPrivateHelper
|
|
71
75
|
form.input name, label: false, required: false, value: value,
|
72
76
|
as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_date_time_picker) ? :effective_date_time_picker : :string),
|
73
77
|
placeholder: placeholder,
|
78
|
+
wrapper_html: wrapper_html,
|
74
79
|
input_group: false,
|
75
80
|
input_html: { name: nil, value: value, title: title, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} },
|
76
81
|
input_js: { useStrict: true, keepInvalid: true } # Keep invalid format like "2015-11" so we can still filter by year, month or day
|
@@ -81,6 +86,7 @@ module EffectiveDatatablesPrivateHelper
|
|
81
86
|
selected: opts[:filter][:selected],
|
82
87
|
multiple: opts[:filter][:multiple] == true,
|
83
88
|
include_blank: include_blank,
|
89
|
+
wrapper_html: wrapper_html,
|
84
90
|
input_html: { name: nil, value: value, title: title, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} },
|
85
91
|
input_js: { placeholder: placeholder }
|
86
92
|
when :grouped_select
|
@@ -94,6 +100,7 @@ module EffectiveDatatablesPrivateHelper
|
|
94
100
|
polymorphic: opts[:filter][:polymorphic] == true,
|
95
101
|
group_label_method: opts[:filter][:group_label_method] || :first,
|
96
102
|
group_method: opts[:filter][:group_method] || :last,
|
103
|
+
wrapper_html: wrapper_html,
|
97
104
|
input_html: { name: nil, value: value, title: title, autocomplete: 'off', data: {'column-name' => opts[:name], 'column-index' => opts[:index]} },
|
98
105
|
input_js: { placeholder: placeholder }
|
99
106
|
when :bulk_actions_column
|
@@ -84,7 +84,7 @@ module Effective
|
|
84
84
|
private
|
85
85
|
|
86
86
|
def display_index(column)
|
87
|
-
display_table_columns.present? ? display_table_columns.keys.index(column[:name]) : column[:
|
87
|
+
display_table_columns.present? ? display_table_columns.keys.index(column[:name]) : column[:index]
|
88
88
|
end
|
89
89
|
|
90
90
|
end
|
@@ -8,6 +8,7 @@ module Effective
|
|
8
8
|
delegate :render, :controller, :link_to, :mail_to, :number_to_currency, :number_to_percentage, :to => :@view
|
9
9
|
|
10
10
|
extend Effective::EffectiveDatatable::Dsl
|
11
|
+
|
11
12
|
include Effective::EffectiveDatatable::Dsl::BulkActions
|
12
13
|
include Effective::EffectiveDatatable::Dsl::Charts
|
13
14
|
include Effective::EffectiveDatatable::Dsl::Datatable
|
@@ -83,7 +84,7 @@ module Effective
|
|
83
84
|
end
|
84
85
|
|
85
86
|
def to_param
|
86
|
-
@to_param ||= self.class.name.underscore
|
87
|
+
@to_param ||= self.class.name.underscore
|
87
88
|
end
|
88
89
|
|
89
90
|
def collection
|
@@ -101,12 +102,12 @@ module Effective
|
|
101
102
|
data = table_data
|
102
103
|
|
103
104
|
{
|
104
|
-
:
|
105
|
-
:
|
106
|
-
:
|
107
|
-
:
|
108
|
-
:
|
109
|
-
:
|
105
|
+
draw: (params[:draw] || 0),
|
106
|
+
data: (data || []),
|
107
|
+
recordsTotal: (total_records || 0),
|
108
|
+
recordsFiltered: (display_records || 0),
|
109
|
+
aggregates: (aggregate_data(data) || []),
|
110
|
+
charts: (charts_data || {})
|
110
111
|
}
|
111
112
|
end
|
112
113
|
end
|
@@ -8,21 +8,21 @@ module Effective
|
|
8
8
|
end
|
9
9
|
|
10
10
|
# Override this function to perform custom searching on a column
|
11
|
-
def search_column(collection, table_column, search_term,
|
11
|
+
def search_column(collection, table_column, search_term, sql_column_or_index)
|
12
12
|
if table_column[:array_column]
|
13
|
-
array_tool.search_column_with_defaults(collection, table_column, search_term,
|
13
|
+
array_tool.search_column_with_defaults(collection, table_column, search_term, sql_column_or_index)
|
14
14
|
else
|
15
|
-
table_tool.search_column_with_defaults(collection, table_column, search_term,
|
15
|
+
table_tool.search_column_with_defaults(collection, table_column, search_term, sql_column_or_index)
|
16
16
|
end
|
17
17
|
end
|
18
18
|
|
19
19
|
# Override this function to perform custom ordering on a column
|
20
20
|
# direction will be :asc or :desc
|
21
|
-
def order_column(collection, table_column, direction,
|
21
|
+
def order_column(collection, table_column, direction, sql_column_or_index)
|
22
22
|
if table_column[:array_column]
|
23
|
-
array_tool.order_column_with_defaults(collection, table_column, direction,
|
23
|
+
array_tool.order_column_with_defaults(collection, table_column, direction, sql_column_or_index)
|
24
24
|
else
|
25
|
-
table_tool.order_column_with_defaults(collection, table_column, direction,
|
25
|
+
table_tool.order_column_with_defaults(collection, table_column, direction, sql_column_or_index)
|
26
26
|
end
|
27
27
|
end
|
28
28
|
end
|
@@ -85,17 +85,12 @@ module Effective
|
|
85
85
|
end
|
86
86
|
|
87
87
|
table_columns = cols.each_with_index do |(name, _), index|
|
88
|
-
# If this is a belongs_to, add an :if clause specifying a collection scope if
|
89
|
-
if belong_tos.key?(name)
|
90
|
-
cols[name][:if] ||= Proc.new { attributes[belong_tos[name][:foreign_key]].blank? }
|
91
|
-
end
|
92
|
-
|
93
88
|
sql_column = (collection.columns rescue []).find do |column|
|
94
89
|
column.name == name.to_s || (belong_tos.key?(name) && column.name == belong_tos[name][:foreign_key])
|
95
90
|
end
|
96
91
|
|
97
92
|
cols[name][:array_column] ||= false
|
98
|
-
cols[name][:
|
93
|
+
cols[name][:index] = index # The index of this column in the collection, regardless of hidden table_columns
|
99
94
|
cols[name][:name] ||= name
|
100
95
|
cols[name][:label] ||= name.titleize
|
101
96
|
cols[name][:column] ||= (sql_table && sql_column) ? "#{quote_sql(sql_table.name)}.#{quote_sql(sql_column.name)}" : name
|
@@ -163,19 +158,6 @@ module Effective
|
|
163
158
|
end
|
164
159
|
end
|
165
160
|
|
166
|
-
# After everything is initialized
|
167
|
-
# Compute any col[:if] and assign an index
|
168
|
-
count = 0
|
169
|
-
table_columns.each do |name, col|
|
170
|
-
if display_column?(col)
|
171
|
-
col[:index] = count
|
172
|
-
count += 1
|
173
|
-
else
|
174
|
-
# deleting rather than using `table_columns.select` above in order to maintain
|
175
|
-
# this hash as a type of HashWithIndifferentAccess
|
176
|
-
table_columns.delete(name)
|
177
|
-
end
|
178
|
-
end
|
179
161
|
end
|
180
162
|
|
181
163
|
def initialize_table_column_filter(column, belongs_to, has_many, has_and_belongs_to_manys)
|
@@ -279,15 +261,6 @@ module Effective
|
|
279
261
|
end.merge(filter.symbolize_keys)
|
280
262
|
end
|
281
263
|
|
282
|
-
private
|
283
|
-
|
284
|
-
def display_column?(col)
|
285
|
-
if col[:if].respond_to?(:call)
|
286
|
-
(view || self).instance_exec(&col[:if])
|
287
|
-
else
|
288
|
-
col.fetch(:if, true)
|
289
|
-
end
|
290
|
-
end
|
291
264
|
end
|
292
265
|
end
|
293
266
|
end
|
@@ -94,7 +94,7 @@ module Effective
|
|
94
94
|
if active_record_collection?
|
95
95
|
view.instance_exec(obj, collection, self, &opts[:block])
|
96
96
|
else
|
97
|
-
view.instance_exec(obj, obj[opts[:
|
97
|
+
view.instance_exec(obj, obj[opts[:index]], collection, self, &opts[:block])
|
98
98
|
end
|
99
99
|
rescue NoMethodError => e
|
100
100
|
if opts[:type] == :actions && e.message == 'super called outside of method'
|
@@ -107,7 +107,7 @@ module Effective
|
|
107
107
|
if active_record_collection?
|
108
108
|
view.instance_exec(obj, collection, self, &opts[:proc])
|
109
109
|
else
|
110
|
-
view.instance_exec(obj, obj[opts[:
|
110
|
+
view.instance_exec(obj, obj[opts[:index]], collection, self, &opts[:proc])
|
111
111
|
end
|
112
112
|
elsif opts[:partial]
|
113
113
|
rendered[name][index]
|
@@ -130,7 +130,7 @@ module Effective
|
|
130
130
|
elsif opts[:type] == :effective_roles
|
131
131
|
(obj.send(:roles) rescue [])
|
132
132
|
elsif obj.kind_of?(Array) # Array backed collection
|
133
|
-
obj[opts[:
|
133
|
+
obj[opts[:index]]
|
134
134
|
elsif opts[:sql_as_column]
|
135
135
|
obj[name] || obj.send(name)
|
136
136
|
else
|
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.10.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: 2017-01-
|
11
|
+
date: 2017-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -122,6 +122,7 @@ files:
|
|
122
122
|
- app/assets/javascripts/effective_datatables.js
|
123
123
|
- app/assets/javascripts/effective_datatables/bulk_actions.js.coffee
|
124
124
|
- app/assets/javascripts/effective_datatables/charts.js.coffee
|
125
|
+
- app/assets/javascripts/effective_datatables/events.js.coffee
|
125
126
|
- app/assets/javascripts/effective_datatables/initialize.js.coffee
|
126
127
|
- app/assets/javascripts/effective_datatables/responsive.js.coffee
|
127
128
|
- app/assets/javascripts/effective_datatables/scopes.js.coffee
|