effective_datatables 3.6.3 → 3.7.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/MIT-LICENSE +1 -1
- data/app/assets/javascripts/dataTables/locales/en.lang +33 -0
- data/app/assets/javascripts/dataTables/locales/es.lang +36 -0
- data/app/assets/javascripts/dataTables/locales/nl.lang +30 -0
- data/app/assets/javascripts/effective_datatables/filters.js.coffee +1 -0
- data/app/assets/javascripts/effective_datatables/flash.js.coffee +31 -0
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +41 -53
- data/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +217 -0
- data/app/assets/javascripts/effective_datatables/overrides.js.coffee +7 -0
- data/app/assets/javascripts/effective_datatables/reorder.js.coffee +43 -0
- data/app/assets/javascripts/effective_datatables/reset.js.coffee +1 -1
- data/app/assets/stylesheets/effective_datatables/_overrides.scss +28 -0
- data/app/controllers/effective/datatables_controller.rb +39 -6
- data/app/datatables/effective_style_guide_datatable.rb +47 -0
- data/app/helpers/effective_datatables_helper.rb +49 -56
- data/app/helpers/effective_datatables_private_helper.rb +137 -11
- data/app/models/effective/datatable.rb +36 -16
- data/app/models/effective/datatable_column.rb +1 -0
- data/app/models/effective/datatable_value_tool.rb +20 -20
- data/app/models/effective/effective_datatable/attributes.rb +5 -13
- data/app/models/effective/effective_datatable/collection.rb +18 -3
- data/app/models/effective/effective_datatable/compute.rb +15 -6
- data/app/models/effective/effective_datatable/cookie.rb +19 -18
- data/app/models/effective/effective_datatable/dsl.rb +8 -3
- data/app/models/effective/effective_datatable/dsl/bulk_actions.rb +16 -23
- data/app/models/effective/effective_datatable/dsl/datatable.rb +70 -28
- data/app/models/effective/effective_datatable/dsl/filters.rb +12 -4
- data/app/models/effective/effective_datatable/format.rb +1 -4
- data/app/models/effective/effective_datatable/params.rb +9 -4
- data/app/models/effective/effective_datatable/resource.rb +129 -74
- data/app/models/effective/effective_datatable/state.rb +30 -15
- data/app/views/effective/datatables/_bulk_actions_dropdown.html.haml +3 -5
- data/app/views/effective/datatables/_datatable.html.haml +3 -5
- data/app/views/effective/datatables/_filters.html.haml +4 -24
- data/app/views/effective/datatables/_reorder_column.html.haml +5 -0
- data/app/views/effective/style_guide/_effective_datatables.html.haml +1 -0
- data/config/effective_datatables.rb +8 -21
- data/config/locales/en.yml +12 -0
- data/config/locales/es.yml +12 -0
- data/config/locales/nl.yml +12 -0
- data/config/routes.rb +5 -4
- data/lib/effective_datatables.rb +49 -2
- data/lib/effective_datatables/engine.rb +4 -2
- data/lib/effective_datatables/version.rb +1 -1
- metadata +17 -5
- data/app/views/effective/datatables/_reset.html.haml +0 -2
@@ -3,16 +3,16 @@ module Effective
|
|
3
3
|
module Dsl
|
4
4
|
module BulkActions
|
5
5
|
|
6
|
-
def bulk_action(
|
7
|
-
datatable._bulk_actions.push(
|
6
|
+
def bulk_action(title, url, opts = {})
|
7
|
+
datatable._bulk_actions.push(link_to_bulk_action(title, url, opts))
|
8
8
|
end
|
9
9
|
|
10
|
-
def bulk_download(
|
11
|
-
datatable._bulk_actions.push(
|
10
|
+
def bulk_download(title, url, opts = {})
|
11
|
+
datatable._bulk_actions.push(link_to_bulk_action(title, url, opts.merge('data-bulk-download': true)))
|
12
12
|
end
|
13
13
|
|
14
14
|
def bulk_action_divider
|
15
|
-
datatable._bulk_actions.push(content_tag(:
|
15
|
+
datatable._bulk_actions.push(content_tag(:div, '', class: 'dropdown-divider'))
|
16
16
|
end
|
17
17
|
|
18
18
|
def bulk_action_content(&block)
|
@@ -22,26 +22,19 @@ module Effective
|
|
22
22
|
private
|
23
23
|
|
24
24
|
# We can't let any data-method be applied to the link, or jquery_ujs does the wrong thing with it
|
25
|
-
def link_to_bulk_action(
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
arg.delete('data-method') ||
|
31
|
-
(arg[:data] || {}).delete('method') ||
|
32
|
-
(arg[:data] || {}).delete(:method)
|
33
|
-
)
|
34
|
-
|
35
|
-
# But if the data-method was :get, we add bulk-actions-get-link = true
|
36
|
-
if data_method.to_s == 'get'
|
37
|
-
arg[:data].present? ? arg[:data]['bulk-actions-get'] = true : arg['data-bulk-actions-get'] = true
|
38
|
-
end
|
39
|
-
end
|
40
|
-
|
41
|
-
arg
|
25
|
+
def link_to_bulk_action(title, url, opts = {})
|
26
|
+
|
27
|
+
# Transform data: { ... } hash into 'data-' keys
|
28
|
+
if (data = opts.delete(:data))
|
29
|
+
data.each { |k, v| opts["data-#{k}"] ||= v }
|
42
30
|
end
|
43
31
|
|
44
|
-
|
32
|
+
verbs = {'DELETE' => 'DELETE', 'GET' => 'GET'}
|
33
|
+
opts['data-ajax-method'] = verbs[opts.delete('data-method').to_s.upcase] || 'POST'
|
34
|
+
|
35
|
+
opts[:class] = [opts[:class], 'dropdown-item'].compact.join(' ')
|
36
|
+
|
37
|
+
content_tag(:li, link_to(title, url, opts))
|
45
38
|
end
|
46
39
|
|
47
40
|
end
|
@@ -3,6 +3,11 @@ module Effective
|
|
3
3
|
module Dsl
|
4
4
|
module Datatable
|
5
5
|
# Instance Methods inside the datatable do .. end block
|
6
|
+
def length(length)
|
7
|
+
raise 'length must be 5, 10, 25, 50, 100, 250, 500, :all' unless [5, 10, 25, 50, 100, 250, 500, :all].include?(length)
|
8
|
+
datatable.state[:length] ||= (length == :all ? 9999999 : length)
|
9
|
+
end
|
10
|
+
|
6
11
|
def order(name, dir = nil)
|
7
12
|
raise 'order direction must be :asc or :desc' unless [nil, :asc, :desc].include?(dir)
|
8
13
|
|
@@ -10,9 +15,13 @@ module Effective
|
|
10
15
|
datatable.state[:order_dir] ||= dir
|
11
16
|
end
|
12
17
|
|
13
|
-
def
|
14
|
-
raise '
|
15
|
-
|
18
|
+
def reorder(name, dir = nil)
|
19
|
+
raise 'order direction must be :asc or :desc' unless [nil, :asc, :desc].include?(dir)
|
20
|
+
|
21
|
+
datatable.state[:order_name] = :_reorder
|
22
|
+
datatable.state[:order_dir] = dir
|
23
|
+
|
24
|
+
reorder_col(name)
|
16
25
|
end
|
17
26
|
|
18
27
|
# A col has its internal values sorted/searched before the block is run
|
@@ -25,7 +34,7 @@ module Effective
|
|
25
34
|
name = name.to_sym unless name.to_s.include?('.')
|
26
35
|
|
27
36
|
datatable._columns[name] = Effective::DatatableColumn.new(
|
28
|
-
action: action,
|
37
|
+
action: action,
|
29
38
|
as: as,
|
30
39
|
compute: nil,
|
31
40
|
col_class: col_class,
|
@@ -53,7 +62,7 @@ module Effective
|
|
53
62
|
name = name.to_sym unless name.to_s.include?('.')
|
54
63
|
|
55
64
|
datatable._columns[name] = Effective::DatatableColumn.new(
|
56
|
-
action: action,
|
65
|
+
action: action,
|
57
66
|
as: as,
|
58
67
|
compute: (compute if block_given?),
|
59
68
|
col_class: col_class,
|
@@ -73,8 +82,48 @@ module Effective
|
|
73
82
|
)
|
74
83
|
end
|
75
84
|
|
76
|
-
def
|
77
|
-
raise 'You can only have one
|
85
|
+
def actions_col(btn_class: nil, col_class: nil, inline: nil, partial: nil, partial_as: nil, actions_partial: nil, responsive: 5000, visible: true, **actions, &format)
|
86
|
+
raise 'You can only have one actions column' if datatable.columns[:_actions].present?
|
87
|
+
|
88
|
+
datatable._columns[:_actions] = Effective::DatatableColumn.new(
|
89
|
+
action: false,
|
90
|
+
as: :actions,
|
91
|
+
compute: nil,
|
92
|
+
btn_class: (btn_class || 'btn-sm btn-outline-primary'),
|
93
|
+
col_class: col_class,
|
94
|
+
format: (format if block_given?),
|
95
|
+
index: nil,
|
96
|
+
inline: (inline.nil? ? datatable.inline? : inline),
|
97
|
+
label: false,
|
98
|
+
name: :actions,
|
99
|
+
partial: partial,
|
100
|
+
partial_as: partial_as,
|
101
|
+
actions_partial: (actions_partial || :glyphicons),
|
102
|
+
responsive: responsive,
|
103
|
+
search: false,
|
104
|
+
sort: false,
|
105
|
+
sql_column: nil,
|
106
|
+
th: nil,
|
107
|
+
th_append: nil,
|
108
|
+
visible: visible,
|
109
|
+
|
110
|
+
# { approve: false }. These args are passed to effective_resources render_resource_actions
|
111
|
+
actions: actions
|
112
|
+
)
|
113
|
+
end
|
114
|
+
|
115
|
+
def aggregate(name, label: nil, &compute)
|
116
|
+
datatable._aggregates[name.to_sym] = {
|
117
|
+
compute: (compute if block_given?),
|
118
|
+
label: label || name.to_s.titleize,
|
119
|
+
name: name.to_sym,
|
120
|
+
}
|
121
|
+
end
|
122
|
+
|
123
|
+
# Called automatically after bulk_actions do ... end
|
124
|
+
# Call again if you want to change the position of the bulk_actions_col
|
125
|
+
def bulk_actions_col(col_class: nil, input_name: nil, partial: nil, partial_as: nil, responsive: 5000)
|
126
|
+
datatable._columns.delete(:_bulk_actions) if datatable.columns[:_bulk_actions]
|
78
127
|
|
79
128
|
datatable._columns[:_bulk_actions] = Effective::DatatableColumn.new(
|
80
129
|
action: false,
|
@@ -83,6 +132,7 @@ module Effective
|
|
83
132
|
col_class: col_class,
|
84
133
|
format: nil,
|
85
134
|
index: nil,
|
135
|
+
input_name: (input_name || 'bulk_actions_resources'),
|
86
136
|
label: false,
|
87
137
|
name: :bulk_actions,
|
88
138
|
partial: partial || '/effective/datatables/bulk_actions_column',
|
@@ -97,41 +147,33 @@ module Effective
|
|
97
147
|
)
|
98
148
|
end
|
99
149
|
|
100
|
-
|
101
|
-
|
150
|
+
# Called automatically after reorder
|
151
|
+
# Call again if you want to change the position of the reorder_col
|
152
|
+
def reorder_col(name, col_class: nil, partial: nil, partial_as: nil, sql_column: nil, responsive: 5000)
|
153
|
+
datatable._columns.delete(:_reorder) if datatable.columns[:_reorder]
|
102
154
|
|
103
|
-
datatable._columns[:
|
155
|
+
datatable._columns[:_reorder] = Effective::DatatableColumn.new(
|
104
156
|
action: false,
|
105
|
-
as: :
|
157
|
+
as: :reorder,
|
106
158
|
compute: nil,
|
107
159
|
col_class: col_class,
|
108
|
-
format:
|
160
|
+
format: nil,
|
109
161
|
index: nil,
|
110
162
|
label: false,
|
111
|
-
name: :
|
112
|
-
partial: partial,
|
163
|
+
name: :reorder,
|
164
|
+
partial: partial || '/effective/datatables/reorder_column',
|
113
165
|
partial_as: partial_as,
|
114
|
-
|
166
|
+
reorder: name,
|
115
167
|
responsive: responsive,
|
116
168
|
search: false,
|
117
|
-
sort:
|
118
|
-
sql_column:
|
169
|
+
sort: true,
|
170
|
+
sql_column: (sql_column || name),
|
119
171
|
th: nil,
|
120
172
|
th_append: nil,
|
121
|
-
visible:
|
122
|
-
|
123
|
-
# { approve: false }. These args are passed to effective_resources render_resource_actions
|
124
|
-
actions: actions
|
173
|
+
visible: false
|
125
174
|
)
|
126
175
|
end
|
127
176
|
|
128
|
-
def aggregate(name, label: nil, &compute)
|
129
|
-
datatable._aggregates[name.to_sym] = {
|
130
|
-
compute: (compute if block_given?),
|
131
|
-
label: label || name.to_s.titleize,
|
132
|
-
name: name.to_sym,
|
133
|
-
}
|
134
|
-
end
|
135
177
|
end
|
136
178
|
end
|
137
179
|
end
|
@@ -5,7 +5,7 @@ module Effective
|
|
5
5
|
def filter(name = nil, value = :_no_value, as: nil, label: nil, parse: nil, required: false, **input_html)
|
6
6
|
return datatable.filter if (name == nil && value == :_no_value) # This lets block methods call 'filter' and get the values
|
7
7
|
|
8
|
-
raise 'expected second argument to be a value' if value == :_no_value
|
8
|
+
raise 'expected second argument to be a value. the default value for this filter.' if value == :_no_value
|
9
9
|
raise 'parse must be a Proc' if parse.present? && !parse.kind_of?(Proc)
|
10
10
|
|
11
11
|
# Merge search
|
@@ -13,15 +13,23 @@ module Effective
|
|
13
13
|
input_html = input_html.merge(input_html[:search])
|
14
14
|
end
|
15
15
|
|
16
|
+
# Try to guess as value
|
17
|
+
as ||= (
|
18
|
+
if input_html.key?(:collection)
|
19
|
+
:select
|
20
|
+
elsif value != nil
|
21
|
+
Effective::Attribute.new(value).type
|
22
|
+
end
|
23
|
+
) || :text
|
24
|
+
|
16
25
|
datatable._filters[name.to_sym] = {
|
17
26
|
value: value,
|
18
27
|
as: as,
|
19
|
-
label: label
|
28
|
+
label: label,
|
20
29
|
name: name.to_sym,
|
21
30
|
parse: parse,
|
22
31
|
required: required,
|
23
|
-
|
24
|
-
}
|
32
|
+
}.compact.reverse_merge(input_html)
|
25
33
|
end
|
26
34
|
|
27
35
|
def scope(name = nil, *args, default: nil, label: nil)
|
@@ -84,10 +84,7 @@ module Effective
|
|
84
84
|
when :actions
|
85
85
|
raise("please use actions_col instead of col(#{name}, as: :actions)")
|
86
86
|
when :boolean
|
87
|
-
|
88
|
-
when true ; 'Yes'
|
89
|
-
when false ; 'No'
|
90
|
-
end
|
87
|
+
view.t("effective_datatables.boolean_#{value}")
|
91
88
|
when :currency
|
92
89
|
view.number_to_currency(value)
|
93
90
|
when :date
|
@@ -7,8 +7,13 @@ module Effective
|
|
7
7
|
def datatables_ajax_request?
|
8
8
|
return @_datatables_ajax_request unless @_datatables_ajax_request.nil?
|
9
9
|
|
10
|
-
@_datatables_ajax_request =
|
11
|
-
|
10
|
+
@_datatables_ajax_request = (view.present? && view.params.key?(:draw) && view.params.key?(:columns))
|
11
|
+
end
|
12
|
+
|
13
|
+
def datatables_inline_request?
|
14
|
+
return @_datatables_inline_request unless @_datatables_inline_request.nil?
|
15
|
+
|
16
|
+
@_datatables_inline_request = (view.present? && view.params[:_datatable_id].to_s.split('-')[0...-1] == to_param.split('-')[0...-1])
|
12
17
|
end
|
13
18
|
|
14
19
|
def params
|
@@ -20,7 +25,7 @@ module Effective
|
|
20
25
|
end
|
21
26
|
|
22
27
|
def filter_params
|
23
|
-
params.select { |name, value| _filters.key?(name.to_sym) }
|
28
|
+
params.select { |name, value| _filters.key?(name.to_sym) && name != 'id' }
|
24
29
|
end
|
25
30
|
|
26
31
|
def scope_param
|
@@ -29,7 +34,7 @@ module Effective
|
|
29
34
|
|
30
35
|
def search_params
|
31
36
|
params.select do |name, value|
|
32
|
-
columns.key?(name) && (name
|
37
|
+
columns.key?(name) && ![:id, :action].include?(name) && !value.kind_of?(Hash) && value.class.name != 'ActionController::Parameters'.freeze
|
33
38
|
end
|
34
39
|
end
|
35
40
|
end
|
@@ -8,7 +8,11 @@ module Effective
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def controller_namespace
|
11
|
-
@attributes[:
|
11
|
+
@attributes[:namespace]
|
12
|
+
end
|
13
|
+
|
14
|
+
def association_macros
|
15
|
+
[:belongs_to, :belongs_to_polymorphic, :has_many, :has_and_belongs_to_many, :has_one]
|
12
16
|
end
|
13
17
|
|
14
18
|
private
|
@@ -23,99 +27,129 @@ module Effective
|
|
23
27
|
def load_resource!
|
24
28
|
load_effective_resource!
|
25
29
|
|
26
|
-
|
27
|
-
|
30
|
+
load_active_record_collection!
|
31
|
+
load_active_record_array_collection!
|
32
|
+
load_array_collection!
|
28
33
|
|
29
|
-
|
30
|
-
|
31
|
-
|
34
|
+
load_resource_columns!
|
35
|
+
load_resource_belongs_tos!
|
36
|
+
load_resource_search!
|
37
|
+
end
|
32
38
|
|
33
|
-
|
39
|
+
def load_effective_resource!
|
40
|
+
@effective_resource = if active_record_collection?
|
41
|
+
Effective::Resource.new(collection_class, namespace: controller_namespace)
|
42
|
+
end
|
43
|
+
end
|
34
44
|
|
35
|
-
|
36
|
-
|
37
|
-
end
|
45
|
+
def load_active_record_collection!
|
46
|
+
return unless active_record_collection?
|
38
47
|
|
39
|
-
|
48
|
+
columns.each do |name, opts|
|
49
|
+
# col 'comments.title'
|
50
|
+
if name.kind_of?(String) && name.include?('.')
|
51
|
+
raise "invalid datatables column '#{name}'. the joined syntax only supports one dot." if name.scan(/\./).count > 1
|
40
52
|
|
41
|
-
|
42
|
-
raise "your datatables collection must .joins(:#{associated}) or .left_outer_joins(:#{associated}) to work with the joined syntax"
|
43
|
-
end
|
53
|
+
(associated, field) = name.split('.').first(2)
|
44
54
|
|
45
|
-
|
55
|
+
unless association_macros.include?(effective_resource.sql_type(associated))
|
56
|
+
raise "invalid datatables column '#{name}'. unable to find '#{name.split('.').first}' association on '#{effective_resource}'."
|
57
|
+
end
|
46
58
|
|
47
|
-
|
48
|
-
opts[:as] ||= opts[:resource].sql_type(field)
|
49
|
-
opts[:as] = :integer if opts[:resource].sql_type(field) == :belongs_to && field.end_with?('_id')
|
50
|
-
opts[:sql_column] = opts[:resource].sql_column(field) if opts[:sql_column].nil?
|
59
|
+
joins_values = (collection.joins_values + collection.left_outer_joins_values)
|
51
60
|
|
52
|
-
|
53
|
-
|
54
|
-
|
61
|
+
unless joins_values.include?(associated.to_sym)
|
62
|
+
raise "your datatables collection must .joins(:#{associated}) or .left_outer_joins(:#{associated}) to work with the joined syntax"
|
63
|
+
end
|
55
64
|
|
56
|
-
|
65
|
+
opts[:resource] = Effective::Resource.new(effective_resource.associated(associated), namespace: controller_namespace)
|
57
66
|
|
58
|
-
|
67
|
+
if opts[:resource].column(field)
|
68
|
+
opts[:as] ||= opts[:resource].sql_type(field)
|
69
|
+
opts[:as] = :integer if opts[:resource].sql_type(field) == :belongs_to && field.end_with?('_id')
|
70
|
+
opts[:sql_column] = opts[:resource].sql_column(field) if opts[:sql_column].nil?
|
71
|
+
|
72
|
+
opts[:resource].sort_column = field
|
73
|
+
opts[:resource].search_columns = field
|
59
74
|
end
|
60
75
|
|
61
|
-
|
62
|
-
|
63
|
-
|
76
|
+
opts[:resource_field] = field
|
77
|
+
|
78
|
+
next
|
79
|
+
end
|
80
|
+
|
81
|
+
# Regular fields
|
82
|
+
opts[:as] ||= effective_resource.sql_type(name)
|
83
|
+
opts[:sql_column] = effective_resource.sql_column(name) if opts[:sql_column].nil?
|
64
84
|
|
65
|
-
|
66
|
-
|
67
|
-
|
85
|
+
case opts[:as]
|
86
|
+
when *association_macros
|
87
|
+
opts[:resource] ||= Effective::Resource.new(effective_resource.associated(name), namespace: controller_namespace)
|
88
|
+
opts[:sql_column] = name if opts[:sql_column].nil?
|
89
|
+
when Class
|
90
|
+
if opts[:as].ancestors.include?(ActiveRecord::Base)
|
91
|
+
opts[:resource] = Effective::Resource.new(opts[:as], namespace: controller_namespace)
|
92
|
+
opts[:as] = :resource
|
68
93
|
opts[:sql_column] = name if opts[:sql_column].nil?
|
69
|
-
when Class
|
70
|
-
if opts[:as].ancestors.include?(ActiveRecord::Base)
|
71
|
-
opts[:resource] = Effective::Resource.new(opts[:as], namespace: controller_namespace)
|
72
|
-
opts[:as] = :resource
|
73
|
-
opts[:sql_column] = name if opts[:sql_column].nil?
|
74
|
-
end
|
75
|
-
when :effective_addresses
|
76
|
-
opts[:resource] = Effective::Resource.new(resource.associated(name), namespace: controller_namespace)
|
77
|
-
opts[:sql_column] = :effective_addresses
|
78
|
-
when :effective_roles
|
79
|
-
opts[:sql_column] = :effective_roles
|
80
|
-
when :string # This is the fallback
|
81
|
-
# Anything that doesn't belong to the model or the sql table, we assume is a SELECT SUM|AVG|RANK() as fancy
|
82
|
-
opts[:sql_as_column] = true if (resource.table && resource.column(name).blank?)
|
83
94
|
end
|
95
|
+
when :effective_addresses
|
96
|
+
opts[:resource] = Effective::Resource.new(effective_resource.associated(name), namespace: controller_namespace)
|
97
|
+
opts[:sql_column] = :effective_addresses
|
98
|
+
when :effective_roles
|
99
|
+
opts[:sql_column] = :effective_roles
|
100
|
+
when :string # This is the fallback
|
101
|
+
# Anything that doesn't belong to the model or the sql table, we assume is a SELECT SUM|AVG|RANK() as fancy
|
102
|
+
opts[:sql_as_column] = true if (effective_resource.table && effective_resource.column(name).blank?)
|
103
|
+
end
|
84
104
|
|
85
|
-
|
86
|
-
|
87
|
-
end
|
105
|
+
if opts[:sql_column].present? && AGGREGATE_SQL_FUNCTIONS.any? { |str| opts[:sql_column].to_s.start_with?(str) }
|
106
|
+
opts[:sql_as_column] = true
|
88
107
|
end
|
89
108
|
end
|
109
|
+
end
|
90
110
|
|
91
|
-
|
92
|
-
|
111
|
+
def load_active_record_array_collection!
|
112
|
+
return unless active_record_array_collection?
|
113
|
+
end
|
93
114
|
|
94
|
-
|
95
|
-
|
96
|
-
|
115
|
+
def load_array_collection!
|
116
|
+
return unless array_collection?
|
117
|
+
|
118
|
+
row = collection.first
|
119
|
+
|
120
|
+
columns.each do |name, opts|
|
121
|
+
if opts[:as].kind_of?(Class) && opts[:as].ancestors.include?(ActiveRecord::Base)
|
122
|
+
opts[:resource] = Effective::Resource.new(opts[:as], namespace: controller_namespace)
|
123
|
+
opts[:as] = :resource
|
124
|
+
elsif opts[:as] == nil && row.present?
|
125
|
+
if (value = Array(row[opts[:index]]).first).kind_of?(ActiveRecord::Base)
|
126
|
+
opts[:resource] = Effective::Resource.new(value, namespace: controller_namespace)
|
97
127
|
opts[:as] = :resource
|
98
|
-
elsif opts[:as] == nil
|
99
|
-
if (value = Array(row[opts[:index]]).first).kind_of?(ActiveRecord::Base)
|
100
|
-
opts[:resource] = Effective::Resource.new(value, namespace: controller_namespace)
|
101
|
-
opts[:as] = :resource
|
102
|
-
end
|
103
128
|
end
|
104
129
|
end
|
105
130
|
end
|
131
|
+
end
|
106
132
|
|
133
|
+
def load_resource_columns!
|
107
134
|
columns.each do |name, opts|
|
108
135
|
opts[:as] ||= :string
|
109
136
|
opts[:as] = :email if (opts[:as] == :string && name.to_s.end_with?('email'))
|
110
137
|
|
138
|
+
if opts[:action]
|
139
|
+
opts[:resource] ||= effective_resource
|
140
|
+
end
|
141
|
+
|
111
142
|
if opts[:resource] && !opts[:resource_field] && opts[:as] != :effective_addresses
|
112
143
|
opts[:partial] ||= '/effective/datatables/resource_column'
|
113
144
|
end
|
114
145
|
|
115
|
-
opts[:col_class] =
|
146
|
+
opts[:col_class] = [
|
147
|
+
"col-#{opts[:as]}",
|
148
|
+
"col-#{name.to_s.parameterize}",
|
149
|
+
('colvis-default' if opts[:visible]),
|
150
|
+
opts[:col_class].presence
|
151
|
+
].compact.join(' ')
|
116
152
|
end
|
117
|
-
|
118
|
-
load_resource_search!
|
119
153
|
end
|
120
154
|
|
121
155
|
def load_resource_search!
|
@@ -127,7 +161,7 @@ module Effective
|
|
127
161
|
when Symbol
|
128
162
|
opts[:search] = { as: opts[:search] }
|
129
163
|
when Array, ActiveRecord::Relation
|
130
|
-
opts[:search] = { collection: opts[:search] }
|
164
|
+
opts[:search] = { as: :select, collection: opts[:search] }
|
131
165
|
when Hash
|
132
166
|
# Nothing
|
133
167
|
else
|
@@ -136,31 +170,35 @@ module Effective
|
|
136
170
|
|
137
171
|
search = opts[:search]
|
138
172
|
|
173
|
+
# Parameterize collection
|
139
174
|
if search[:collection].kind_of?(ActiveRecord::Relation)
|
140
175
|
search[:collection] = search[:collection].map { |obj| [obj.to_s, obj.to_param] }
|
141
176
|
elsif search[:collection].kind_of?(Array) && search[:collection].first.kind_of?(ActiveRecord::Base)
|
142
177
|
search[:collection] = search[:collection].map { |obj| [obj.to_s, obj.to_param] }
|
143
|
-
elsif search[:collection].kind_of?(Array)
|
144
|
-
search[:collection].each { |obj| obj[1] = 'nil' if obj[1] == nil }
|
145
|
-
elsif search[:collection].kind_of?(Hash)
|
146
|
-
search[:collection].each { |k, v| search[:collection][k] = 'nil' if v == nil }
|
147
178
|
end
|
148
179
|
|
180
|
+
search[:as] ||= :select if search.key?(:collection)
|
181
|
+
search[:fuzzy] ||= true unless search.key?(:fuzzy)
|
149
182
|
search[:value] ||= search.delete(:selected) if search.key?(:selected)
|
150
183
|
|
151
|
-
|
152
|
-
|
153
|
-
|
184
|
+
# Merge with defaults
|
185
|
+
search_resource = [opts[:resource], effective_resource, fallback_effective_resource].compact
|
186
|
+
search_resource = search_resource.find { |res| res.klass.present? } || search_resource.first
|
154
187
|
|
155
188
|
if array_collection? && opts[:resource].present?
|
156
|
-
search.reverse_merge!(
|
189
|
+
search.reverse_merge!(search_resource.search_form_field(name, collection.first[opts[:index]]))
|
157
190
|
elsif search[:as] != :string
|
158
|
-
search.reverse_merge!(
|
191
|
+
search.reverse_merge!(search_resource.search_form_field(name, opts[:as]))
|
192
|
+
end
|
193
|
+
|
194
|
+
# Assign default include_null
|
195
|
+
if search[:as] == :select && !search.key?(:include_null)
|
196
|
+
search[:include_null] = true
|
159
197
|
end
|
160
198
|
end
|
161
199
|
end
|
162
200
|
|
163
|
-
def
|
201
|
+
def load_resource_belongs_tos!
|
164
202
|
return unless active_record_collection?
|
165
203
|
|
166
204
|
changed = attributes.select do |attribute, value|
|
@@ -168,10 +206,27 @@ module Effective
|
|
168
206
|
next unless attribute.ends_with?('_id')
|
169
207
|
|
170
208
|
associated = attribute.gsub(/_id\z/, '').to_sym # Replace last _id
|
171
|
-
next unless columns[associated] && columns[associated][:as] == :belongs_to
|
172
209
|
|
173
|
-
|
174
|
-
|
210
|
+
next unless columns[associated]
|
211
|
+
|
212
|
+
if columns[associated][:as] == :belongs_to
|
213
|
+
if @_collection_apply_belongs_to && !@_collection.where_values_hash.include?(attribute)
|
214
|
+
@_collection = @_collection.where(attribute => value)
|
215
|
+
end
|
216
|
+
|
217
|
+
columns.delete(associated)
|
218
|
+
elsif columns[associated][:as] == :belongs_to_polymorphic
|
219
|
+
associated_type = attributes["#{associated}_type".to_sym] || raise("Expected #{associated}_type attribute to be present when #{associated}_id is present on a polymorphic belongs to")
|
220
|
+
|
221
|
+
if @_collection_apply_belongs_to
|
222
|
+
if !@_collection.where_values_hash.include?(attribute) && !@_collection.where_values_hash.include?("#{associated}_type")
|
223
|
+
@_collection = @_collection.where(attribute => value).where("#{associated}_type" => associated_type)
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
columns.delete(associated)
|
228
|
+
end
|
229
|
+
|
175
230
|
end.present?
|
176
231
|
|
177
232
|
load_columns! if changed
|