effective_datatables 3.6.3 → 3.7.0
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/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
|