effective_datatables 4.7.16 → 4.15.1
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/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 }
|