effective_datatables 3.7.7 → 4.0.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 +5 -5
- data/MIT-LICENSE +1 -1
- data/README.md +32 -32
- data/app/assets/images/dataTables/sort-down.svg +1 -0
- data/app/assets/images/dataTables/sort-up.svg +1 -0
- data/app/assets/images/dataTables/sort.svg +1 -0
- data/app/assets/javascripts/dataTables/buttons/{buttons.bootstrap.js → buttons.bootstrap4.js} +7 -15
- data/app/assets/javascripts/dataTables/dataTables.bootstrap4.js +184 -0
- data/app/assets/javascripts/dataTables/responsive/dataTables.responsive.js +30 -11
- data/app/assets/javascripts/dataTables/responsive/{responsive.bootstrap.js → responsive.bootstrap4.js} +6 -6
- data/app/assets/javascripts/effective_datatables.js +4 -4
- data/app/assets/javascripts/effective_datatables/bulk_actions.js.coffee +43 -43
- data/app/assets/javascripts/effective_datatables/events.js.coffee +7 -4
- data/app/assets/javascripts/effective_datatables/filters.js.coffee +0 -1
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +45 -49
- data/app/assets/javascripts/effective_datatables/overrides.js +12 -0
- data/app/assets/javascripts/effective_datatables/reset.js.coffee +1 -1
- data/app/assets/stylesheets/dataTables/buttons/{buttons.bootstrap.scss → buttons.bootstrap4.css} +68 -1
- data/app/assets/stylesheets/dataTables/{dataTables.bootstrap.scss → dataTables.bootstrap4.css} +44 -29
- data/app/assets/stylesheets/dataTables/responsive/{responsive.bootstrap.scss → responsive.bootstrap4.css} +3 -3
- data/app/assets/stylesheets/effective_datatables.scss +3 -4
- data/app/assets/stylesheets/effective_datatables/_overrides.scss +72 -152
- data/app/controllers/effective/datatables_controller.rb +6 -39
- data/app/helpers/effective_datatables_helper.rb +55 -50
- data/app/helpers/effective_datatables_private_helper.rb +47 -179
- data/app/models/effective/datatable.rb +16 -44
- data/app/models/effective/datatable_column.rb +0 -1
- data/app/models/effective/datatable_column_tool.rb +1 -1
- data/app/models/effective/datatable_dsl_tool.rb +3 -11
- data/app/models/effective/datatable_value_tool.rb +23 -23
- data/app/models/effective/effective_datatable/attributes.rb +13 -5
- data/app/models/effective/effective_datatable/collection.rb +3 -18
- data/app/models/effective/effective_datatable/compute.rb +6 -17
- data/app/models/effective/effective_datatable/cookie.rb +20 -19
- data/app/models/effective/effective_datatable/dsl.rb +3 -8
- data/app/models/effective/effective_datatable/dsl/bulk_actions.rb +25 -14
- data/app/models/effective/effective_datatable/dsl/datatable.rb +28 -70
- data/app/models/effective/effective_datatable/dsl/filters.rb +5 -5
- data/app/models/effective/effective_datatable/format.rb +50 -95
- data/app/models/effective/effective_datatable/params.rb +3 -8
- data/app/models/effective/effective_datatable/resource.rb +76 -137
- data/app/models/effective/effective_datatable/state.rb +15 -30
- data/app/views/effective/datatables/_actions_column.html.haml +8 -1
- data/app/views/effective/datatables/_bulk_actions_column.html.haml +1 -1
- data/app/views/effective/datatables/_filters.html.haml +11 -12
- data/app/views/effective/datatables/_resource_column.html.haml +8 -11
- data/config/effective_datatables.rb +14 -12
- data/config/routes.rb +0 -1
- data/lib/effective_datatables.rb +4 -57
- data/lib/effective_datatables/engine.rb +1 -1
- data/lib/effective_datatables/version.rb +1 -1
- metadata +20 -30
- data/app/assets/images/dataTables/sort_asc.png +0 -0
- data/app/assets/images/dataTables/sort_both.png +0 -0
- data/app/assets/images/dataTables/sort_desc.png +0 -0
- data/app/assets/javascripts/dataTables/dataTables.bootstrap.js +0 -182
- data/app/assets/javascripts/dataTables/locales/en.lang +0 -33
- data/app/assets/javascripts/dataTables/locales/es.lang +0 -36
- data/app/assets/javascripts/dataTables/locales/nl.lang +0 -30
- data/app/assets/javascripts/effective_datatables/flash.js.coffee +0 -31
- data/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +0 -217
- data/app/assets/javascripts/effective_datatables/overrides.js.coffee +0 -7
- data/app/assets/javascripts/effective_datatables/reorder.js.coffee +0 -43
- data/app/assets/stylesheets/effective_datatables/_filters.scss +0 -7
- data/app/views/effective/datatables/_reorder_column.html.haml +0 -5
- data/config/locales/en.yml +0 -12
- data/config/locales/es.yml +0 -12
- data/config/locales/nl.yml +0 -12
@@ -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
|
8
|
+
raise 'expected second argument to be a value' 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
|
@@ -17,19 +17,19 @@ module Effective
|
|
17
17
|
as ||= (
|
18
18
|
if input_html.key?(:collection)
|
19
19
|
:select
|
20
|
-
elsif value
|
20
|
+
elsif value.present?
|
21
21
|
Effective::Attribute.new(value).type
|
22
22
|
end
|
23
|
-
)
|
23
|
+
)
|
24
24
|
|
25
25
|
datatable._filters[name.to_sym] = {
|
26
26
|
value: value,
|
27
27
|
as: as,
|
28
|
-
label: label,
|
28
|
+
label: label || (label == false ? false : name.to_s.titleize),
|
29
29
|
name: name.to_sym,
|
30
30
|
parse: parse,
|
31
31
|
required: required,
|
32
|
-
}.
|
32
|
+
}.reverse_merge(input_html)
|
33
33
|
end
|
34
34
|
|
35
35
|
def scope(name = nil, *args, default: nil, label: nil)
|
@@ -2,9 +2,6 @@ module Effective
|
|
2
2
|
module EffectiveDatatable
|
3
3
|
module Format
|
4
4
|
BLANK = ''.freeze
|
5
|
-
NONVISIBLE = '...'.freeze
|
6
|
-
SPACER = 'EFFECTIVEDATATABLESSPACER'.freeze
|
7
|
-
SPACER_TEMPLATE = '/effective/datatables/spacer_template'.freeze
|
8
5
|
|
9
6
|
private
|
10
7
|
|
@@ -13,10 +10,12 @@ module Effective
|
|
13
10
|
rendered = {}
|
14
11
|
|
15
12
|
columns.each do |name, opts|
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
if opts[:partial] && state[:visible][name]
|
14
|
+
locals = {
|
15
|
+
datatable: self,
|
16
|
+
column: columns[name],
|
17
|
+
controller_namespace: controller_namespace
|
18
|
+
}.merge(actions_col_locals(opts)).merge(resource_col_locals(opts))
|
20
19
|
|
21
20
|
rendered[name] = (view.render(
|
22
21
|
partial: opts[:partial],
|
@@ -24,42 +23,20 @@ module Effective
|
|
24
23
|
collection: collection.map { |row| row[opts[:index]] },
|
25
24
|
formats: :html,
|
26
25
|
locals: locals,
|
27
|
-
spacer_template:
|
28
|
-
) || '').split(
|
29
|
-
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
|
-
locals = { datatable: self, column: opts, spacer_template: SPACER_TEMPLATE }
|
32
|
-
|
33
|
-
atts = {
|
34
|
-
actions: actions_col_actions(opts),
|
35
|
-
btn_class: opts[:btn_class],
|
36
|
-
effective_resource: effective_resource,
|
37
|
-
locals: locals,
|
38
|
-
partial: opts[:actions_partial],
|
39
|
-
}.compact.merge(opts[:actions])
|
40
|
-
|
41
|
-
rendered[name] = if effective_resource.blank?
|
42
|
-
resources.map do |resource|
|
43
|
-
polymorphic_resource = Effective::Resource.new(resource, namespace: controller_namespace)
|
44
|
-
(view.render_resource_actions(resource, atts.merge(effective_resource: polymorphic_resource), &opts[:format]) || '')
|
45
|
-
end
|
46
|
-
else
|
47
|
-
(view.render_resource_actions(resources, atts, &opts[:format]) || '').split(SPACER)
|
48
|
-
end
|
26
|
+
spacer_template: '/effective/datatables/spacer_template',
|
27
|
+
) || '').split('EFFECTIVEDATATABLESSPACER')
|
49
28
|
end
|
50
29
|
end
|
51
30
|
|
52
31
|
collection.each_with_index do |row, row_index|
|
53
32
|
columns.each do |name, opts|
|
33
|
+
next unless state[:visible][name]
|
34
|
+
|
54
35
|
index = opts[:index]
|
55
36
|
value = row[index]
|
56
37
|
|
57
38
|
row[index] = (
|
58
|
-
if
|
59
|
-
NONVISIBLE
|
60
|
-
elsif opts[:as] == :actions
|
61
|
-
rendered[name][row_index]
|
62
|
-
elsif opts[:format] && rendered.key?(name)
|
39
|
+
if opts[:format] && rendered.key?(name)
|
63
40
|
dsl_tool.instance_exec(value, row, rendered[name][row_index], &opts[:format])
|
64
41
|
elsif opts[:format]
|
65
42
|
dsl_tool.instance_exec(value, row, &opts[:format])
|
@@ -81,22 +58,23 @@ module Effective
|
|
81
58
|
end
|
82
59
|
|
83
60
|
case column[:as]
|
84
|
-
when :actions
|
85
|
-
raise("please use actions_col instead of col(#{name}, as: :actions)")
|
86
61
|
when :boolean
|
87
|
-
|
62
|
+
case value
|
63
|
+
when true ; 'Yes'
|
64
|
+
when false ; 'No'
|
65
|
+
end
|
88
66
|
when :currency
|
89
67
|
view.number_to_currency(value)
|
90
68
|
when :date
|
91
|
-
|
69
|
+
(value.strftime('%F') rescue BLANK)
|
92
70
|
when :datetime
|
93
|
-
|
71
|
+
(value.strftime('%F %H:%M') rescue BLANK)
|
94
72
|
when :decimal
|
95
73
|
value
|
96
74
|
when :duration
|
97
75
|
view.number_to_duration(value)
|
98
76
|
when :effective_addresses
|
99
|
-
|
77
|
+
value.to_html
|
100
78
|
when :effective_obfuscation
|
101
79
|
value
|
102
80
|
when :effective_roles
|
@@ -105,10 +83,10 @@ module Effective
|
|
105
83
|
view.mail_to(value)
|
106
84
|
when :integer
|
107
85
|
value
|
108
|
-
when :
|
86
|
+
when :percentage
|
109
87
|
case value
|
110
|
-
when Integer ;
|
111
|
-
when Numeric ; view.number_to_percentage(value, precision:
|
88
|
+
when Integer ; "#{value}%"
|
89
|
+
when Numeric ; view.number_to_percentage(value * 100, precision: 2)
|
112
90
|
end
|
113
91
|
when :price
|
114
92
|
case value
|
@@ -116,74 +94,51 @@ module Effective
|
|
116
94
|
when Numeric ; view.number_to_currency(value)
|
117
95
|
end
|
118
96
|
when :time
|
119
|
-
|
97
|
+
(value.strftime('%H:%M') rescue BLANK)
|
120
98
|
else
|
121
99
|
value.to_s
|
122
100
|
end
|
123
101
|
end
|
124
102
|
|
125
|
-
|
126
|
-
|
127
|
-
# Merges in any extra attributes when passed as a Hash
|
128
|
-
def actions_col_actions(column)
|
129
|
-
resource_actions = (effective_resource.try(:resource_actions) || fallback_effective_resource.fallback_resource_actions)
|
130
|
-
|
131
|
-
actions = if column[:inline]
|
132
|
-
resource_actions.transform_values { |opts| opts['data-remote'] = true; opts }
|
133
|
-
else
|
134
|
-
resource_actions.transform_values { |opts| opts['data-remote'] = true if opts['data-method']; opts }
|
135
|
-
end
|
136
|
-
|
137
|
-
# Merge local options. Special behaviour for remote: false
|
138
|
-
if column[:actions].kind_of?(Hash)
|
139
|
-
column[:actions].each do |action, opts|
|
140
|
-
next unless opts.kind_of?(Hash)
|
141
|
-
|
142
|
-
existing = actions.find { |_, v| v[:action] == action }.try(:first)
|
143
|
-
next unless existing.present?
|
103
|
+
def actions_col_locals(opts)
|
104
|
+
return {} unless opts[:as] == :actions
|
144
105
|
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
(
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
106
|
+
locals = {
|
107
|
+
show_action: (
|
108
|
+
active_record_collection? && opts[:show] && resource.routes[:show] &&
|
109
|
+
EffectiveDatatables.authorized?(view.controller, :show, collection_class)
|
110
|
+
),
|
111
|
+
edit_action: (
|
112
|
+
active_record_collection? && opts[:edit] && resource.routes[:edit] &&
|
113
|
+
EffectiveDatatables.authorized?(view.controller, :edit, collection_class)
|
114
|
+
),
|
115
|
+
destroy_action: (
|
116
|
+
active_record_collection? && opts[:destroy] && resource.routes[:destroy] &&
|
117
|
+
EffectiveDatatables.authorized?(view.controller, :destroy, collection_class)
|
118
|
+
),
|
119
|
+
effective_resource: resource
|
120
|
+
}
|
158
121
|
end
|
159
122
|
|
160
123
|
def resource_col_locals(opts)
|
161
|
-
return {} unless (
|
162
|
-
|
163
|
-
associated = associated_resource.macros.include?(opts[:as])
|
164
|
-
polymorphic = (opts[:as] == :belongs_to_polymorphic)
|
165
|
-
|
166
|
-
resource_name = opts[:name] if associated
|
167
|
-
resource_to_s = opts[:name] unless associated || array_collection?
|
124
|
+
return {} unless (resource = opts[:resource]).present?
|
168
125
|
|
169
|
-
locals = {
|
170
|
-
resource_name: resource_name,
|
171
|
-
resource_to_s: resource_to_s,
|
172
|
-
effective_resource: associated_resource,
|
173
|
-
show_action: false,
|
174
|
-
edit_action: false
|
175
|
-
}
|
126
|
+
locals = { name: opts[:name], effective_resource: resource, show_action: false, edit_action: false }
|
176
127
|
|
177
128
|
case opts[:action]
|
178
129
|
when :edit
|
179
|
-
locals[:edit_action] = (
|
130
|
+
locals[:edit_action] = (resource.routes[:edit] && EffectiveDatatables.authorized?(view.controller, :edit, resource.klass))
|
180
131
|
when :show
|
181
|
-
locals[:show_action] = (
|
132
|
+
locals[:show_action] = (resource.routes[:show] && EffectiveDatatables.authorized?(view.controller, :show, resource.klass))
|
182
133
|
when false
|
183
|
-
# Nothing
|
134
|
+
# Nothing
|
184
135
|
else
|
185
|
-
|
186
|
-
|
136
|
+
# Fallback to defaults - check edit then show
|
137
|
+
if resource.routes[:edit] && EffectiveDatatables.authorized?(view.controller, :edit, resource.klass)
|
138
|
+
locals[:edit_action] = true
|
139
|
+
elsif resource.routes[:show] && EffectiveDatatables.authorized?(view.controller, :show, resource.klass)
|
140
|
+
locals[:show_action] = true
|
141
|
+
end
|
187
142
|
end
|
188
143
|
|
189
144
|
locals
|
@@ -7,13 +7,8 @@ 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
|
-
|
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])
|
10
|
+
@_datatables_ajax_request =
|
11
|
+
(view && view.params[:draw] && view.params[:columns] && cookie_keys.include?(view.params[:cookie])) == true
|
17
12
|
end
|
18
13
|
|
19
14
|
def params
|
@@ -34,7 +29,7 @@ module Effective
|
|
34
29
|
|
35
30
|
def search_params
|
36
31
|
params.select do |name, value|
|
37
|
-
columns.key?(name) &&
|
32
|
+
columns.key?(name) && (name != :id) && !value.kind_of?(Hash) && value.class.name != 'ActionController::Parameters'.freeze
|
38
33
|
end
|
39
34
|
end
|
40
35
|
end
|
@@ -8,148 +8,108 @@ module Effective
|
|
8
8
|
end
|
9
9
|
|
10
10
|
def controller_namespace
|
11
|
-
@attributes[:
|
12
|
-
end
|
13
|
-
|
14
|
-
def association_macros
|
15
|
-
[:belongs_to, :belongs_to_polymorphic, :has_many, :has_and_belongs_to_many, :has_one]
|
11
|
+
@attributes[:_n]
|
16
12
|
end
|
17
13
|
|
18
14
|
private
|
19
15
|
|
20
|
-
def load_effective_resource!
|
21
|
-
@effective_resource = if active_record_collection?
|
22
|
-
Effective::Resource.new(collection_class, namespace: controller_namespace)
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
16
|
# This looks at all the columns and figures out the as:
|
27
17
|
def load_resource!
|
28
|
-
|
18
|
+
@resource = Effective::Resource.new(collection_class, namespace: controller_namespace)
|
29
19
|
|
30
|
-
|
31
|
-
|
32
|
-
load_array_collection!
|
20
|
+
if active_record_collection?
|
21
|
+
columns.each do |name, opts|
|
33
22
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
23
|
+
# col 'comments.title'
|
24
|
+
if name.kind_of?(String) && name.include?('.')
|
25
|
+
raise "invalid datatables column '#{name}'. the joined syntax only supports one dot." if name.scan(/\./).count > 1
|
38
26
|
|
39
|
-
|
40
|
-
@effective_resource = if active_record_collection?
|
41
|
-
Effective::Resource.new(collection_class, namespace: controller_namespace)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def load_active_record_collection!
|
46
|
-
return unless active_record_collection?
|
27
|
+
(associated, field) = name.split('.').first(2)
|
47
28
|
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
raise "invalid datatables column '#{name}'. the joined syntax only supports one dot." if name.scan(/\./).count > 1
|
29
|
+
unless resource.macros.include?(resource.sql_type(associated))
|
30
|
+
raise "invalid datatables column '#{name}'. unable to find '#{name.split('.').first}' association on '#{resource}'."
|
31
|
+
end
|
52
32
|
|
53
|
-
|
33
|
+
joins_values = (collection.joins_values + collection.left_outer_joins_values)
|
54
34
|
|
55
|
-
|
56
|
-
|
57
|
-
|
35
|
+
unless joins_values.include?(associated.to_sym)
|
36
|
+
raise "your datatables collection must .joins(:#{associated}) or .left_outer_joins(:#{associated}) to work with the joined syntax"
|
37
|
+
end
|
58
38
|
|
59
|
-
|
39
|
+
opts[:resource] = Effective::Resource.new(resource.associated(associated), namespace: controller_namespace)
|
60
40
|
|
61
|
-
|
62
|
-
|
63
|
-
|
41
|
+
if opts[:resource].column(field)
|
42
|
+
opts[:as] ||= opts[:resource].sql_type(field)
|
43
|
+
opts[:as] = :integer if opts[:resource].sql_type(field) == :belongs_to && field.end_with?('_id')
|
44
|
+
opts[:sql_column] = opts[:resource].sql_column(field) if opts[:sql_column].nil?
|
64
45
|
|
65
|
-
|
46
|
+
opts[:resource].sort_column = field
|
47
|
+
opts[:resource].search_columns = field
|
48
|
+
end
|
66
49
|
|
67
|
-
|
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?
|
50
|
+
opts[:resource_field] = field
|
71
51
|
|
72
|
-
|
73
|
-
opts[:resource].search_columns = field
|
52
|
+
next
|
74
53
|
end
|
75
54
|
|
76
|
-
|
77
|
-
|
78
|
-
|
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?
|
55
|
+
# Regular fields
|
56
|
+
opts[:as] ||= resource.sql_type(name)
|
57
|
+
opts[:sql_column] = resource.sql_column(name) if opts[:sql_column].nil?
|
84
58
|
|
85
|
-
|
86
|
-
|
87
|
-
|
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
|
59
|
+
case opts[:as]
|
60
|
+
when *resource.macros
|
61
|
+
opts[:resource] ||= Effective::Resource.new(resource.associated(name), namespace: controller_namespace)
|
93
62
|
opts[:sql_column] = name if opts[:sql_column].nil?
|
63
|
+
when Class
|
64
|
+
if opts[:as].ancestors.include?(ActiveRecord::Base)
|
65
|
+
opts[:resource] = Effective::Resource.new(opts[:as], namespace: controller_namespace)
|
66
|
+
opts[:as] = :resource
|
67
|
+
opts[:sql_column] = name if opts[:sql_column].nil?
|
68
|
+
end
|
69
|
+
when :effective_addresses
|
70
|
+
opts[:resource] = Effective::Resource.new(resource.associated(name), namespace: controller_namespace)
|
71
|
+
opts[:sql_column] = :effective_addresses
|
72
|
+
when :effective_roles
|
73
|
+
opts[:sql_column] = :effective_roles
|
74
|
+
when :string # This is the fallback
|
75
|
+
# Anything that doesn't belong to the model or the sql table, we assume is a SELECT SUM|AVG|RANK() as fancy
|
76
|
+
opts[:sql_as_column] = true if (resource.table && resource.column(name).blank?)
|
94
77
|
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
|
104
78
|
|
105
|
-
|
106
|
-
|
79
|
+
if opts[:sql_column].present? && AGGREGATE_SQL_FUNCTIONS.any? { |str| opts[:sql_column].to_s.start_with?(str) }
|
80
|
+
opts[:sql_as_column] = true
|
81
|
+
end
|
107
82
|
end
|
108
83
|
end
|
109
|
-
end
|
110
|
-
|
111
|
-
def load_active_record_array_collection!
|
112
|
-
return unless active_record_array_collection?
|
113
|
-
end
|
114
|
-
|
115
|
-
def load_array_collection!
|
116
|
-
return unless array_collection?
|
117
84
|
|
118
|
-
|
85
|
+
if array_collection?
|
86
|
+
row = collection.first
|
119
87
|
|
120
|
-
|
121
|
-
|
122
|
-
|
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)
|
88
|
+
columns.each do |name, opts|
|
89
|
+
if opts[:as].kind_of?(Class) && opts[:as].ancestors.include?(ActiveRecord::Base)
|
90
|
+
opts[:resource] = Effective::Resource.new(opts[:as], namespace: controller_namespace)
|
127
91
|
opts[:as] = :resource
|
92
|
+
elsif opts[:as] == nil
|
93
|
+
if (value = Array(row[opts[:index]]).first).kind_of?(ActiveRecord::Base)
|
94
|
+
opts[:resource] = Effective::Resource.new(value, namespace: controller_namespace)
|
95
|
+
opts[:as] = :resource
|
96
|
+
end
|
128
97
|
end
|
129
98
|
end
|
130
99
|
end
|
131
|
-
end
|
132
100
|
|
133
|
-
def load_resource_columns!
|
134
101
|
columns.each do |name, opts|
|
135
102
|
opts[:as] ||= :string
|
136
103
|
opts[:as] = :email if (opts[:as] == :string && name.to_s.end_with?('email'))
|
137
104
|
|
138
|
-
if opts[:action]
|
139
|
-
opts[:resource] ||= effective_resource
|
140
|
-
end
|
141
|
-
|
142
105
|
if opts[:resource] && !opts[:resource_field] && opts[:as] != :effective_addresses
|
143
106
|
opts[:partial] ||= '/effective/datatables/resource_column'
|
144
107
|
end
|
145
108
|
|
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(' ')
|
109
|
+
opts[:col_class] = "col-#{opts[:as]} col-#{name.to_s.parameterize} #{opts[:col_class]}".strip
|
152
110
|
end
|
111
|
+
|
112
|
+
load_resource_search!
|
153
113
|
end
|
154
114
|
|
155
115
|
def load_resource_search!
|
@@ -161,7 +121,7 @@ module Effective
|
|
161
121
|
when Symbol
|
162
122
|
opts[:search] = { as: opts[:search] }
|
163
123
|
when Array, ActiveRecord::Relation
|
164
|
-
opts[:search] = {
|
124
|
+
opts[:search] = { collection: opts[:search] }
|
165
125
|
when Hash
|
166
126
|
# Nothing
|
167
127
|
else
|
@@ -170,35 +130,31 @@ module Effective
|
|
170
130
|
|
171
131
|
search = opts[:search]
|
172
132
|
|
173
|
-
# Parameterize collection
|
174
133
|
if search[:collection].kind_of?(ActiveRecord::Relation)
|
175
134
|
search[:collection] = search[:collection].map { |obj| [obj.to_s, obj.to_param] }
|
176
135
|
elsif search[:collection].kind_of?(Array) && search[:collection].first.kind_of?(ActiveRecord::Base)
|
177
136
|
search[:collection] = search[:collection].map { |obj| [obj.to_s, obj.to_param] }
|
137
|
+
elsif search[:collection].kind_of?(Array)
|
138
|
+
search[:collection].each { |obj| obj[1] = 'nil' if obj[1] == nil }
|
139
|
+
elsif search[:collection].kind_of?(Hash)
|
140
|
+
search[:collection].each { |k, v| search[:collection][k] = 'nil' if v == nil }
|
178
141
|
end
|
179
142
|
|
180
|
-
search[:as] ||= :select if search.key?(:collection)
|
181
|
-
search[:fuzzy] ||= true unless search.key?(:fuzzy)
|
182
143
|
search[:value] ||= search.delete(:selected) if search.key?(:selected)
|
183
144
|
|
184
|
-
|
185
|
-
search_resource = [opts[:resource], effective_resource, fallback_effective_resource].compact
|
186
|
-
search_resource = search_resource.find { |res| res.klass.present? } || search_resource.first
|
145
|
+
search[:as] ||= :select if (search.key?(:collection) && opts[:as] != :belongs_to_polymorphic)
|
187
146
|
|
188
|
-
|
189
|
-
search.reverse_merge!(search_resource.search_form_field(name, collection.first[opts[:index]]))
|
190
|
-
elsif search[:as] != :string
|
191
|
-
search.reverse_merge!(search_resource.search_form_field(name, opts[:as]))
|
192
|
-
end
|
147
|
+
search[:fuzzy] = true unless search.key?(:fuzzy)
|
193
148
|
|
194
|
-
|
195
|
-
|
196
|
-
|
149
|
+
if array_collection? && opts[:resource].present?
|
150
|
+
search.reverse_merge!(resource.search_form_field(name, collection.first[opts[:index]]))
|
151
|
+
else
|
152
|
+
search.reverse_merge!(resource.search_form_field(name, opts[:as]))
|
197
153
|
end
|
198
154
|
end
|
199
155
|
end
|
200
156
|
|
201
|
-
def
|
157
|
+
def apply_belongs_to_attributes!
|
202
158
|
return unless active_record_collection?
|
203
159
|
|
204
160
|
changed = attributes.select do |attribute, value|
|
@@ -206,27 +162,10 @@ module Effective
|
|
206
162
|
next unless attribute.ends_with?('_id')
|
207
163
|
|
208
164
|
associated = attribute.gsub(/_id\z/, '').to_sym # Replace last _id
|
165
|
+
next unless columns[associated] && columns[associated][:as] == :belongs_to
|
209
166
|
|
210
|
-
|
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
|
-
|
167
|
+
@_collection = @_collection.where(attribute => value)
|
168
|
+
columns.delete(associated)
|
230
169
|
end.present?
|
231
170
|
|
232
171
|
load_columns! if changed
|