effective_datatables 4.7.16 → 4.15.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +278 -24
- data/app/assets/javascripts/effective_datatables/bulk_actions.js.coffee +32 -9
- data/app/assets/javascripts/effective_datatables/download.js.coffee +10 -0
- data/app/assets/javascripts/effective_datatables/flash.js.coffee +1 -1
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +22 -13
- data/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +42 -13
- data/app/assets/javascripts/effective_datatables/reorder.js.coffee +8 -2
- data/app/assets/javascripts/effective_datatables/reset.js.coffee +23 -2
- data/app/assets/javascripts/vendor/jquery.delayedChange.js +1 -2
- data/app/assets/stylesheets/dataTables/dataTables.bootstrap4.scss +1 -3
- data/app/controllers/effective/datatables_controller.rb +34 -0
- data/app/helpers/effective_datatables_controller_helper.rb +2 -0
- data/app/helpers/effective_datatables_helper.rb +22 -6
- data/app/helpers/effective_datatables_private_helper.rb +30 -20
- data/app/models/effective/datatable.rb +57 -4
- data/app/models/effective/datatable_column.rb +2 -0
- data/app/models/effective/datatable_column_tool.rb +5 -3
- data/app/models/effective/datatable_dsl_tool.rb +7 -5
- data/app/models/effective/datatable_value_tool.rb +9 -8
- data/app/models/effective/effective_datatable/attributes.rb +21 -0
- data/app/models/effective/effective_datatable/collection.rb +3 -1
- data/app/models/effective/effective_datatable/compute.rb +11 -7
- data/app/models/effective/effective_datatable/cookie.rb +6 -0
- data/app/models/effective/effective_datatable/csv.rb +71 -0
- data/app/models/effective/effective_datatable/dsl/bulk_actions.rb +3 -1
- data/app/models/effective/effective_datatable/dsl/charts.rb +2 -0
- data/app/models/effective/effective_datatable/dsl/datatable.rb +20 -6
- data/app/models/effective/effective_datatable/dsl/filters.rb +3 -1
- data/app/models/effective/effective_datatable/dsl.rb +7 -3
- data/app/models/effective/effective_datatable/format.rb +52 -24
- data/app/models/effective/effective_datatable/hooks.rb +2 -0
- data/app/models/effective/effective_datatable/params.rb +9 -2
- data/app/models/effective/effective_datatable/resource.rb +26 -13
- data/app/models/effective/effective_datatable/state.rb +4 -2
- data/app/views/effective/datatables/_active_storage_column.html.haml +4 -0
- data/app/views/effective/datatables/_bulk_actions_dropdown.html.haml +3 -2
- data/app/views/effective/datatables/_buttons.html.haml +14 -0
- data/config/effective_datatables.rb +8 -1
- data/config/locales/en.yml +4 -1
- data/config/locales/es.yml +4 -1
- data/config/locales/nl.yml +4 -1
- data/config/routes.rb +1 -0
- data/lib/effective_datatables/engine.rb +6 -4
- data/lib/effective_datatables/version.rb +1 -1
- data/lib/effective_datatables.rb +5 -0
- metadata +11 -10
- data/app/datatables/effective_style_guide_datatable.rb +0 -47
- data/app/models/effective/access_denied.rb +0 -17
- data/app/views/effective/style_guide/_effective_datatables.html.haml +0 -1
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
|
3
5
|
class DatatableDslTool
|
@@ -16,7 +18,7 @@ module Effective
|
|
16
18
|
@view = datatable.view
|
17
19
|
end
|
18
20
|
|
19
|
-
def method_missing(method, *args, &block)
|
21
|
+
def method_missing(method, *args, **kwargs, &block)
|
20
22
|
# Catch a common error
|
21
23
|
if [:bulk_actions, :charts, :collection, :filters].include?(method) && in_datatables_do_block
|
22
24
|
raise "#{method} block must be declared outside the datatable do ... end block"
|
@@ -24,15 +26,15 @@ module Effective
|
|
24
26
|
|
25
27
|
if datatable.respond_to?(method)
|
26
28
|
if block_given?
|
27
|
-
datatable.send(method, *args) { yield }
|
29
|
+
datatable.send(method, *args, **kwargs) { yield }
|
28
30
|
else
|
29
|
-
datatable.send(method, *args)
|
31
|
+
datatable.send(method, *args, **kwargs)
|
30
32
|
end
|
31
33
|
elsif view.respond_to?(method)
|
32
34
|
if block_given?
|
33
|
-
view.send(method, *args) { yield }
|
35
|
+
view.send(method, *args, **kwargs) { yield }
|
34
36
|
else
|
35
|
-
view.send(method, *args)
|
37
|
+
view.send(method, *args, **kwargs)
|
36
38
|
end
|
37
39
|
else
|
38
40
|
super
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
# The collection is an Array of Arrays
|
3
5
|
class DatatableValueTool
|
@@ -77,7 +79,7 @@ module Effective
|
|
77
79
|
def search_column(collection, original, column, index)
|
78
80
|
Rails.logger.info "VALUE TOOL: search_column #{column.to_s} #{original} #{index}" if EffectiveDatatables.debug
|
79
81
|
|
80
|
-
fuzzy = column[:search][:
|
82
|
+
fuzzy = (column[:search][:operation] == :matches)
|
81
83
|
|
82
84
|
term = Effective::Attribute.new(column[:as]).parse(original, name: column[:name])
|
83
85
|
term_downcased = term.to_s.downcase
|
@@ -91,8 +93,11 @@ module Effective
|
|
91
93
|
collection.select! do |row|
|
92
94
|
obj = row[index]
|
93
95
|
value = obj_to_value(row[index], column, row)
|
96
|
+
next if value.nil? || value == ''
|
97
|
+
|
98
|
+
obj_equals = obj.respond_to?(column[:name]) && obj.send(column[:name]).to_s.downcase == term_downcased
|
94
99
|
|
95
|
-
case column[:as]
|
100
|
+
obj_equals || case column[:as]
|
96
101
|
when :boolean
|
97
102
|
if fuzzy
|
98
103
|
term ? (obj == true) : (obj != true)
|
@@ -174,6 +179,8 @@ module Effective
|
|
174
179
|
|
175
180
|
if column[:format]
|
176
181
|
datatable.dsl_tool.instance_exec(obj, row, &column[:format])
|
182
|
+
elsif column[:as] == :belongs_to_polymorphic
|
183
|
+
obj.send(column[:name]).to_s
|
177
184
|
elsif column[:partial]
|
178
185
|
obj.to_s
|
179
186
|
elsif obj.respond_to?(column[:name])
|
@@ -187,9 +194,3 @@ module Effective
|
|
187
194
|
|
188
195
|
end
|
189
196
|
end
|
190
|
-
|
191
|
-
# [
|
192
|
-
# [1, 'title 1'],
|
193
|
-
# [2, 'title 2'],
|
194
|
-
# [3, 'title 3']
|
195
|
-
# ]
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Attributes
|
@@ -11,9 +13,28 @@ module Effective
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def load_attributes!
|
16
|
+
return unless view.respond_to?(:controller_path)
|
14
17
|
@attributes[:namespace] ||= view.controller_path.split('/')[0...-1].join('/')
|
15
18
|
end
|
16
19
|
|
20
|
+
# Polymorphic shorthand attributes.
|
21
|
+
# If you pass resource: User(1), it sets resource_id: 1, resource_type: 'User'
|
22
|
+
def initial_attributes(attributes)
|
23
|
+
return {} if attributes.blank?
|
24
|
+
|
25
|
+
resources = attributes.select { |k, v| v.kind_of?(ActiveRecord::Base) }
|
26
|
+
return attributes if resources.blank?
|
27
|
+
|
28
|
+
retval = attributes.except(*resources.keys)
|
29
|
+
|
30
|
+
resources.each do |k, resource|
|
31
|
+
retval["#{k}_id".to_sym] = resource.id
|
32
|
+
retval["#{k}_type".to_sym] = resource.class.name
|
33
|
+
end
|
34
|
+
|
35
|
+
retval
|
36
|
+
end
|
37
|
+
|
17
38
|
end
|
18
39
|
end
|
19
40
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Collection
|
@@ -34,7 +36,7 @@ module Effective
|
|
34
36
|
raise 'No collection defined. Please add a collection with collection do ... end' if collection.nil?
|
35
37
|
|
36
38
|
@collection_class = (collection.respond_to?(:klass) ? collection.klass : self.class)
|
37
|
-
|
39
|
+
|
38
40
|
@active_record_collection = (collection.ancestors.include?(ActiveRecord::Base) rescue false)
|
39
41
|
@active_record_array_collection = collection.kind_of?(Array) && collection.present? && collection.first.kind_of?(ActiveRecord::Base)
|
40
42
|
@array_collection = collection.kind_of?(Array) && (collection.blank? || collection.first.kind_of?(Array))
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Compute
|
@@ -36,6 +38,9 @@ module Effective
|
|
36
38
|
# Apply value ordering
|
37
39
|
col = value_tool.order(col)
|
38
40
|
|
41
|
+
# Charts too
|
42
|
+
@charts_data = chart(collection, col) if _charts.present?
|
43
|
+
|
39
44
|
# Apply pagination
|
40
45
|
col = col.kind_of?(Array) ? value_tool.paginate(col) : column_tool.paginate(col)
|
41
46
|
|
@@ -48,9 +53,6 @@ module Effective
|
|
48
53
|
# Compute aggregate data
|
49
54
|
@aggregates_data = aggregate(col) if _aggregates.present?
|
50
55
|
|
51
|
-
# Charts too
|
52
|
-
@charts_data = chart(col) if _charts.present?
|
53
|
-
|
54
56
|
# Format all results
|
55
57
|
format(col)
|
56
58
|
|
@@ -58,10 +60,12 @@ module Effective
|
|
58
60
|
finalize(col)
|
59
61
|
end
|
60
62
|
|
61
|
-
def arrayize(collection)
|
63
|
+
def arrayize(collection, csv: false)
|
62
64
|
collection.map do |obj|
|
63
65
|
columns.map do |name, opts|
|
64
|
-
if state[:visible][name] == false && (name != order_name) # Sort by invisible array column
|
66
|
+
if state[:visible][name] == false && !csv && (name != order_name) # Sort by invisible array column
|
67
|
+
BLANK
|
68
|
+
elsif csv && !opts[:csv]
|
65
69
|
BLANK
|
66
70
|
elsif opts[:compute]
|
67
71
|
if array_collection?
|
@@ -161,11 +165,11 @@ module Effective
|
|
161
165
|
end || BLANK
|
162
166
|
end
|
163
167
|
|
164
|
-
def chart(collection)
|
168
|
+
def chart(collection, searched_collection)
|
165
169
|
_charts.inject({}) do |retval, (name, chart)|
|
166
170
|
retval[name] = {
|
167
171
|
as: chart[:as],
|
168
|
-
data: dsl_tool.instance_exec(collection, &chart[:compute]),
|
172
|
+
data: dsl_tool.instance_exec(collection, searched_collection, &chart[:compute]),
|
169
173
|
name: chart[:name],
|
170
174
|
options: chart[:options]
|
171
175
|
}
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Cookie
|
@@ -10,6 +12,8 @@ module Effective
|
|
10
12
|
|
11
13
|
def load_cookie!
|
12
14
|
return unless EffectiveDatatables.save_state
|
15
|
+
return if skip_save_state?
|
16
|
+
return unless (view.cookies rescue false) # Rails 6.1 view doesn't respond_to?(:cookies)
|
13
17
|
|
14
18
|
@dt_cookie = view.cookies.signed['_effective_dt']
|
15
19
|
|
@@ -33,6 +37,8 @@ module Effective
|
|
33
37
|
|
34
38
|
def save_cookie!
|
35
39
|
return unless EffectiveDatatables.save_state
|
40
|
+
return if skip_save_state?
|
41
|
+
return unless (view.cookies rescue false)
|
36
42
|
|
37
43
|
@dt_cookie ||= []
|
38
44
|
@dt_cookie << [cookie_key, cookie_payload]
|
@@ -0,0 +1,71 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'csv'
|
4
|
+
|
5
|
+
module Effective
|
6
|
+
module EffectiveDatatable
|
7
|
+
module Csv
|
8
|
+
|
9
|
+
def csv_filename
|
10
|
+
self.class.name.underscore.parameterize + '.csv'
|
11
|
+
end
|
12
|
+
|
13
|
+
def csv_content_type
|
14
|
+
'text/csv; charset=utf-8'
|
15
|
+
end
|
16
|
+
|
17
|
+
def csv_header
|
18
|
+
columns.map do |name, opts|
|
19
|
+
opts[:label].presence || csv_human_attribute_name(name)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def csv_human_attribute_name(name)
|
24
|
+
if active_record_collection?
|
25
|
+
collection_class.human_attribute_name(name)
|
26
|
+
else
|
27
|
+
(name.to_s.split('.').last || '')
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def csv_file
|
32
|
+
CSV.generate do |csv|
|
33
|
+
csv << csv_header()
|
34
|
+
|
35
|
+
collection.find_in_batches do |resources|
|
36
|
+
resources = arrayize(resources, csv: true)
|
37
|
+
format(resources, csv: true)
|
38
|
+
finalize(resources)
|
39
|
+
|
40
|
+
resources.each { |resource| csv << resource }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def csv_stream
|
46
|
+
EffectiveResources.with_resource_enumerator do |lines|
|
47
|
+
lines << CSV.generate_line(csv_header)
|
48
|
+
|
49
|
+
if active_record_collection?
|
50
|
+
collection.find_in_batches do |resources|
|
51
|
+
resources = arrayize(resources, csv: true)
|
52
|
+
format(resources, csv: true)
|
53
|
+
finalize(resources)
|
54
|
+
|
55
|
+
resources.each { |resource| lines << CSV.generate_line(resource) }
|
56
|
+
end
|
57
|
+
else
|
58
|
+
resources = collection
|
59
|
+
|
60
|
+
format(resources, csv: true)
|
61
|
+
finalize(resources)
|
62
|
+
|
63
|
+
resources.each { |resource| lines << CSV.generate_line(resource) }
|
64
|
+
end
|
65
|
+
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Dsl
|
@@ -34,7 +36,7 @@ module Effective
|
|
34
36
|
|
35
37
|
opts[:class] = [opts[:class], 'dropdown-item'].compact.join(' ')
|
36
38
|
|
37
|
-
link_to(title, url, opts)
|
39
|
+
link_to(title, url, **opts)
|
38
40
|
end
|
39
41
|
|
40
42
|
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Dsl
|
@@ -24,11 +26,19 @@ module Effective
|
|
24
26
|
reorder_col(name)
|
25
27
|
end
|
26
28
|
|
29
|
+
def download(bool)
|
30
|
+
datatable.attributes[:downloadable] = bool
|
31
|
+
end
|
32
|
+
|
33
|
+
def skip_save_state!
|
34
|
+
datatable.attributes[:skip_save_state] = true
|
35
|
+
end
|
36
|
+
|
27
37
|
# A col has its internal values sorted/searched before the block is run
|
28
38
|
# Anything done in the block, is purely a format on the after sorted/ordered value
|
29
39
|
# the original object == the computed value, which is yielded to the format block
|
30
40
|
# You can't do compute with .col
|
31
|
-
def col(name, action: nil, as: nil, col_class: nil, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: nil, th: nil, th_append: nil, visible: true, &format)
|
41
|
+
def col(name, action: nil, as: nil, col_class: nil, csv: true, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: nil, th: nil, th_append: nil, visible: true, &format)
|
32
42
|
raise 'You cannot use partial: ... with the block syntax' if partial && block_given?
|
33
43
|
|
34
44
|
name = name.to_sym unless name.to_s.include?('.')
|
@@ -38,9 +48,10 @@ module Effective
|
|
38
48
|
as: as,
|
39
49
|
compute: nil,
|
40
50
|
col_class: col_class,
|
51
|
+
csv: csv,
|
41
52
|
format: (format if block_given?),
|
42
53
|
index: nil,
|
43
|
-
label:
|
54
|
+
label: label,
|
44
55
|
name: name,
|
45
56
|
partial: partial,
|
46
57
|
partial_as: partial_as,
|
@@ -56,7 +67,7 @@ module Effective
|
|
56
67
|
|
57
68
|
# A val is a computed value that is then sorted/searched after the block is run
|
58
69
|
# You can have another block by calling .format afterwards to work on the computed value itself
|
59
|
-
def val(name, action: nil, as: nil, col_class: nil, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: false, th: nil, th_append: nil, visible: true, &compute)
|
70
|
+
def val(name, action: nil, as: nil, col_class: nil, csv: true, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: false, th: nil, th_append: nil, visible: true, &compute)
|
60
71
|
raise 'You cannot use partial: ... with the block syntax' if partial && block_given?
|
61
72
|
|
62
73
|
name = name.to_sym unless name.to_s.include?('.')
|
@@ -66,9 +77,10 @@ module Effective
|
|
66
77
|
as: as,
|
67
78
|
compute: (compute if block_given?),
|
68
79
|
col_class: col_class,
|
80
|
+
csv: csv,
|
69
81
|
format: nil,
|
70
82
|
index: nil,
|
71
|
-
label:
|
83
|
+
label: label,
|
72
84
|
name: name,
|
73
85
|
partial: partial,
|
74
86
|
partial_as: partial_as,
|
@@ -82,7 +94,7 @@ module Effective
|
|
82
94
|
)
|
83
95
|
end
|
84
96
|
|
85
|
-
def actions_col(btn_class: nil, col_class: nil,
|
97
|
+
def actions_col(btn_class: nil, col_class: nil, partial: nil, partial_as: nil, actions_partial: nil, responsive: 5000, visible: true, **actions, &format)
|
86
98
|
raise 'You can only have one actions column' if datatable.columns[:_actions].present?
|
87
99
|
|
88
100
|
datatable._columns[:_actions] = Effective::DatatableColumn.new(
|
@@ -91,9 +103,9 @@ module Effective
|
|
91
103
|
compute: nil,
|
92
104
|
btn_class: (btn_class || 'btn-sm btn-outline-primary'),
|
93
105
|
col_class: col_class,
|
106
|
+
csv: false,
|
94
107
|
format: (format if block_given?),
|
95
108
|
index: nil,
|
96
|
-
inline: (inline.nil? ? datatable.inline? : inline),
|
97
109
|
label: false,
|
98
110
|
name: :actions,
|
99
111
|
partial: partial,
|
@@ -130,6 +142,7 @@ module Effective
|
|
130
142
|
as: :bulk_actions,
|
131
143
|
compute: nil,
|
132
144
|
col_class: col_class,
|
145
|
+
csv: false,
|
133
146
|
format: nil,
|
134
147
|
index: nil,
|
135
148
|
input_name: (input_name || 'bulk_actions_resources'),
|
@@ -157,6 +170,7 @@ module Effective
|
|
157
170
|
as: :reorder,
|
158
171
|
compute: nil,
|
159
172
|
col_class: col_class,
|
173
|
+
csv: false,
|
160
174
|
format: nil,
|
161
175
|
index: nil,
|
162
176
|
label: false,
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Dsl
|
@@ -20,7 +22,7 @@ module Effective
|
|
20
22
|
elsif value != nil
|
21
23
|
Effective::Attribute.new(value).type
|
22
24
|
end
|
23
|
-
) || :
|
25
|
+
) || :string
|
24
26
|
|
25
27
|
datatable._filters[name.to_sym] = {
|
26
28
|
value: value,
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Dsl
|
@@ -11,11 +13,11 @@ module Effective
|
|
11
13
|
end
|
12
14
|
|
13
15
|
def collection(apply_belongs_to: true, apply_scope: true, &block)
|
14
|
-
define_method('initialize_collection') {
|
16
|
+
define_method('initialize_collection') {
|
15
17
|
self._collection_apply_belongs_to = apply_belongs_to
|
16
18
|
self._collection_apply_scope = apply_scope
|
17
|
-
|
18
|
-
self._collection = dsl_tool.instance_exec(&block)
|
19
|
+
|
20
|
+
self._collection = dsl_tool.instance_exec(&block)
|
19
21
|
}
|
20
22
|
end
|
21
23
|
|
@@ -24,6 +26,8 @@ module Effective
|
|
24
26
|
dsl_tool.in_datatables_do_block = true
|
25
27
|
dsl_tool.instance_exec(&block)
|
26
28
|
dsl_tool.in_datatables_do_block = false
|
29
|
+
|
30
|
+
self.source_location = block.source_location.first if block.respond_to?(:source_location)
|
27
31
|
end
|
28
32
|
end
|
29
33
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Format
|
@@ -8,15 +10,17 @@ module Effective
|
|
8
10
|
|
9
11
|
private
|
10
12
|
|
11
|
-
def format(collection)
|
13
|
+
def format(collection, csv: false)
|
12
14
|
# We want to use the render :collection for each column that renders partials
|
13
15
|
rendered = {}
|
14
16
|
|
15
17
|
columns.each do |name, opts|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
18
|
+
if state[:visible][name] == false && !csv
|
19
|
+
# Nothing to do
|
20
|
+
elsif csv && !opts[:csv]
|
21
|
+
# Nothing to do
|
22
|
+
elsif opts[:partial]
|
23
|
+
locals = { datatable: self, column: opts }.merge!(resource_col_locals(opts))
|
20
24
|
|
21
25
|
rendered[name] = (view.render(
|
22
26
|
partial: opts[:partial],
|
@@ -26,8 +30,8 @@ module Effective
|
|
26
30
|
locals: locals,
|
27
31
|
spacer_template: SPACER_TEMPLATE
|
28
32
|
) || '').split(SPACER)
|
33
|
+
|
29
34
|
elsif opts[:as] == :actions # This is actions_col and actions_col do .. end, but not actions_col partial: 'something'
|
30
|
-
resources = collection.map { |row| row[opts[:index]] }
|
31
35
|
locals = { datatable: self, column: opts, spacer_template: SPACER_TEMPLATE }
|
32
36
|
|
33
37
|
atts = {
|
@@ -36,15 +40,15 @@ module Effective
|
|
36
40
|
effective_resource: effective_resource,
|
37
41
|
locals: locals,
|
38
42
|
partial: opts[:actions_partial],
|
39
|
-
}.
|
43
|
+
}.merge!(opts[:actions]).tap(&:compact!)
|
40
44
|
|
41
45
|
rendered[name] = if effective_resource.blank?
|
42
|
-
|
46
|
+
collection.map { |row| row[opts[:index]] }.map do |resource|
|
43
47
|
polymorphic_resource = Effective::Resource.new(resource, namespace: controller_namespace)
|
44
48
|
(view.render_resource_actions(resource, atts.merge(effective_resource: polymorphic_resource), &opts[:format]) || '')
|
45
49
|
end
|
46
50
|
else
|
47
|
-
(view.render_resource_actions(
|
51
|
+
(view.render_resource_actions(collection.map { |row| row[opts[:index]] }, atts, &opts[:format]) || '').split(SPACER)
|
48
52
|
end
|
49
53
|
end
|
50
54
|
end
|
@@ -54,32 +58,52 @@ module Effective
|
|
54
58
|
index = opts[:index]
|
55
59
|
value = row[index]
|
56
60
|
|
57
|
-
|
58
|
-
if state[:visible][name] == false
|
61
|
+
formatted = (
|
62
|
+
if state[:visible][name] == false && !csv
|
59
63
|
NONVISIBLE
|
64
|
+
elsif csv && !opts[:csv]
|
65
|
+
BLANK
|
60
66
|
elsif opts[:as] == :actions
|
61
67
|
rendered[name][row_index]
|
62
68
|
elsif opts[:format] && rendered.key?(name)
|
63
69
|
dsl_tool.instance_exec(value, row, rendered[name][row_index], &opts[:format])
|
64
70
|
elsif opts[:format]
|
65
|
-
dsl_tool.instance_exec(value, row, &opts[:format])
|
71
|
+
dsl_tool.instance_exec(value, row, &opts[:format]).to_s
|
66
72
|
elsif opts[:partial]
|
67
73
|
rendered[name][row_index]
|
68
74
|
else
|
69
|
-
format_column(value, opts)
|
75
|
+
format_column(value, opts, csv: csv)
|
70
76
|
end
|
71
77
|
)
|
78
|
+
|
79
|
+
if csv && (opts[:format] || opts[:partial])
|
80
|
+
formatted = view.strip_tags(formatted)
|
81
|
+
|
82
|
+
formatted.gsub!("\n\n", ' ') unless formatted.frozen?
|
83
|
+
formatted.gsub!("\n", '') unless formatted.frozen?
|
84
|
+
end
|
85
|
+
|
86
|
+
row[index] = formatted
|
72
87
|
end
|
73
88
|
end
|
74
89
|
end
|
75
90
|
|
76
|
-
|
91
|
+
# Must return a string
|
92
|
+
def format_column(value, column, csv: false)
|
77
93
|
return if value.nil? || (column[:resource] && value.blank?)
|
78
94
|
|
79
95
|
unless column[:as] == :email
|
80
96
|
return value if value.kind_of?(String)
|
81
97
|
end
|
82
98
|
|
99
|
+
if value.kind_of?(Array) && column[:as] == :string
|
100
|
+
if csv
|
101
|
+
return value.map { |v| format_column(v, column, csv: csv) }.join("\n")
|
102
|
+
else
|
103
|
+
return value.map { |v| view.content_tag(:div, format_column(v, column, csv: csv), class: 'col-resource_item') }.join.html_safe
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
83
107
|
case column[:as]
|
84
108
|
when :actions
|
85
109
|
raise("please use actions_col instead of col(#{name}, as: :actions)")
|
@@ -88,23 +112,27 @@ module Effective
|
|
88
112
|
when :currency
|
89
113
|
view.number_to_currency(value)
|
90
114
|
when :date
|
91
|
-
(value.strftime(
|
115
|
+
value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_date) : BLANK
|
92
116
|
when :datetime
|
93
|
-
|
117
|
+
if csv
|
118
|
+
value.to_s
|
119
|
+
else
|
120
|
+
value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_datetime) : BLANK
|
121
|
+
end
|
94
122
|
when :decimal
|
95
|
-
value
|
123
|
+
value.to_s
|
96
124
|
when :duration
|
97
125
|
view.number_to_duration(value)
|
98
126
|
when :effective_addresses
|
99
|
-
value.to_html
|
127
|
+
csv ? value.to_html.gsub('<br>', "\n") : value.to_html
|
100
128
|
when :effective_obfuscation
|
101
|
-
value
|
129
|
+
value.to_s
|
102
130
|
when :effective_roles
|
103
131
|
value.join(', ')
|
104
132
|
when :email
|
105
|
-
view.mail_to(value)
|
133
|
+
csv ? value : view.mail_to(value)
|
106
134
|
when :integer
|
107
|
-
value
|
135
|
+
value.to_s
|
108
136
|
when :percent
|
109
137
|
case value
|
110
138
|
when Integer ; view.number_to_percentage(value / 1000.0, precision: 3).gsub('.000%', '%')
|
@@ -116,7 +144,7 @@ module Effective
|
|
116
144
|
when Numeric ; view.number_to_currency(value)
|
117
145
|
end
|
118
146
|
when :time
|
119
|
-
(value.strftime(
|
147
|
+
value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_time) : BLANK
|
120
148
|
else
|
121
149
|
value.to_s
|
122
150
|
end
|
@@ -128,14 +156,14 @@ module Effective
|
|
128
156
|
def actions_col_actions(column)
|
129
157
|
resource_actions = (effective_resource&.resource_actions || fallback_effective_resource.fallback_resource_actions)
|
130
158
|
|
131
|
-
actions = if
|
159
|
+
actions = if inline?
|
132
160
|
resource_actions.transform_values { |opts| opts['data-remote'] = true; opts }
|
133
161
|
else
|
134
162
|
resource_actions.transform_values { |opts| opts['data-remote'] = true if opts['data-method']; opts }
|
135
163
|
end
|
136
164
|
|
137
165
|
# Merge local options. Special behaviour for remote: false
|
138
|
-
if column[:actions].kind_of?(Hash)
|
166
|
+
if column[:actions].present? && column[:actions].kind_of?(Hash)
|
139
167
|
column[:actions].each do |action, opts|
|
140
168
|
next unless opts.kind_of?(Hash)
|
141
169
|
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
module EffectiveDatatable
|
3
5
|
module Params
|
@@ -6,18 +8,23 @@ module Effective
|
|
6
8
|
|
7
9
|
def datatables_ajax_request?
|
8
10
|
return @_datatables_ajax_request unless @_datatables_ajax_request.nil?
|
11
|
+
return unless view.respond_to?(:params)
|
9
12
|
|
10
|
-
@_datatables_ajax_request = (view.
|
13
|
+
@_datatables_ajax_request = (view.params.key?(:draw) && view.params.key?(:columns))
|
11
14
|
end
|
12
15
|
|
13
16
|
def datatables_inline_request?
|
14
17
|
return @_datatables_inline_request unless @_datatables_inline_request.nil?
|
18
|
+
return unless view.respond_to?(:params)
|
15
19
|
|
16
|
-
@_datatables_inline_request = (view.
|
20
|
+
@_datatables_inline_request = (view.params[:_datatable_id].to_s.split('-')[0...-1] == to_param.split('-')[0...-1])
|
17
21
|
end
|
18
22
|
|
19
23
|
def params
|
20
24
|
return {} unless view.present?
|
25
|
+
return view.rendered_params if view.respond_to?(:rendered_params)
|
26
|
+
return {} unless view.respond_to?(:request)
|
27
|
+
|
21
28
|
@params ||= {}.tap do |params|
|
22
29
|
Rack::Utils.parse_query(URI(view.request.referer.presence || '/').query).each { |k, v| params[k.to_sym] = v }
|
23
30
|
view.params.each { |k, v| params[k.to_sym] = v }
|