effective_datatables 3.7.10 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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/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/javascripts/effective_datatables.js +4 -4
- 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/_overrides.scss +72 -152
- data/app/assets/stylesheets/effective_datatables.scss +3 -4
- 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 +2 -4
- 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/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/dsl.rb +3 -8
- 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/engine.rb +4 -14
- data/lib/effective_datatables/version.rb +1 -1
- data/lib/effective_datatables.rb +4 -57
- metadata +20 -31
- data/app/assets/config/effective_datatables_manifest.js +0 -3
- 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
@@ -1,21 +1,18 @@
|
|
1
1
|
# These aren't expected to be called by a developer. They are internal methods.
|
2
|
-
# These aren't expected to be called by a developer. They are internal methods.
|
3
2
|
module EffectiveDatatablesPrivateHelper
|
4
3
|
|
5
4
|
# https://datatables.net/reference/option/columns
|
6
5
|
def datatable_columns(datatable)
|
7
|
-
sortable = datatable.sortable?
|
8
|
-
|
9
6
|
datatable.columns.map do |name, opts|
|
10
7
|
{
|
11
|
-
className: opts[:col_class],
|
12
8
|
name: name,
|
9
|
+
title: content_tag(:span, opts[:label].presence),
|
10
|
+
className: opts[:col_class],
|
13
11
|
responsivePriority: opts[:responsive],
|
14
12
|
search: datatable.state[:search][name],
|
15
13
|
searchHtml: datatable_search_tag(datatable, name, opts),
|
16
|
-
sortable: (opts[:sort] &&
|
17
|
-
|
18
|
-
visible: datatable.state[:visible][name]
|
14
|
+
sortable: (opts[:sort] && !datatable.simple?),
|
15
|
+
visible: datatable.state[:visible][name],
|
19
16
|
}
|
20
17
|
end.to_json.html_safe
|
21
18
|
end
|
@@ -26,207 +23,78 @@ module EffectiveDatatablesPrivateHelper
|
|
26
23
|
end
|
27
24
|
end
|
28
25
|
|
29
|
-
def datatable_display_order(datatable)
|
30
|
-
(datatable.sortable? ? [datatable.order_index, datatable.order_direction] : false).to_json.html_safe
|
31
|
-
end
|
32
|
-
|
33
26
|
def datatable_reset(datatable)
|
34
|
-
link_to(content_tag(:span,
|
35
|
-
end
|
36
|
-
|
37
|
-
def datatable_reorder(datatable)
|
38
|
-
return unless datatable.reorder? && EffectiveDatatables.authorized?(self, :update, datatable.collection_class)
|
39
|
-
link_to(content_tag(:span, t('effective_datatables.reorder')), '#', class: 'btn btn-link btn-sm buttons-reorder', disabled: true)
|
40
|
-
end
|
41
|
-
|
42
|
-
def datatable_new_resource_button(datatable, name, column)
|
43
|
-
return unless column[:inline] && (column[:actions][:new] != false)
|
44
|
-
|
45
|
-
action = { action: :new, class: ['btn', column[:btn_class].presence].compact.join(' '), 'data-remote': true }
|
46
|
-
|
47
|
-
if column[:actions][:new].kind_of?(Hash) # This might be active_record_array_collection?
|
48
|
-
action = action.merge(column[:actions][:new])
|
49
|
-
|
50
|
-
effective_resource = (datatable.effective_resource || datatable.fallback_effective_resource)
|
51
|
-
klass = (column[:actions][:new][:klass] || effective_resource.try(:klass) || datatable.collection_class)
|
52
|
-
elsif Array(datatable.effective_resource.try(:actions)).include?(:new)
|
53
|
-
effective_resource = datatable.effective_resource
|
54
|
-
klass = effective_resource.klass
|
55
|
-
else
|
56
|
-
return
|
57
|
-
end
|
58
|
-
|
59
|
-
# Will only work if permitted
|
60
|
-
render_resource_actions(klass, actions: { t('effective_datatables.new') => action }, effective_resource: effective_resource)
|
61
|
-
end
|
62
|
-
|
63
|
-
def datatable_label_tag(datatable, name, opts)
|
64
|
-
case opts[:as]
|
65
|
-
when :actions
|
66
|
-
content_tag(:span, t('effective_datatables.actions'), style: 'display: none;')
|
67
|
-
when :bulk_actions
|
68
|
-
content_tag(:span, t('effective_datatables.bulk_actions'), style: 'display: none;')
|
69
|
-
when :reorder
|
70
|
-
content_tag(:span, t('effective_datatables.reorder'), style: 'display: none;')
|
71
|
-
else
|
72
|
-
content_tag(:span, opts[:label].presence)
|
73
|
-
end
|
27
|
+
link_to(content_tag(:span, 'Reset'), '#', class: 'btn btn-link btn-sm buttons-reset-search')
|
74
28
|
end
|
75
29
|
|
76
30
|
def datatable_search_tag(datatable, name, opts)
|
77
|
-
return datatable_new_resource_button(datatable, name, opts) if name == :_actions
|
78
|
-
|
79
31
|
return if opts[:search] == false
|
80
32
|
|
81
33
|
# Build the search
|
82
|
-
@_effective_datatables_form_builder ||
|
34
|
+
@_effective_datatables_form_builder || effective_form_with(scope: :datatable_search, url: '#') { |f| @_effective_datatables_form_builder = f }
|
83
35
|
form = @_effective_datatables_form_builder
|
84
36
|
|
85
|
-
include_blank = opts[:search].key?(:include_blank) ? opts[:search][:include_blank] : opts[:label]
|
86
|
-
pattern = opts[:search][:pattern]
|
87
|
-
placeholder = opts[:search][:placeholder] || ''
|
88
|
-
title = opts[:search][:title] || opts[:label]
|
89
|
-
wrapper_html = { class: 'datatable_search' }
|
90
|
-
|
91
37
|
collection = opts[:search].delete(:collection)
|
92
38
|
value = datatable.state[:search][name]
|
93
39
|
|
94
|
-
|
40
|
+
options = opts[:search].except(:fuzzy).merge!(
|
95
41
|
name: nil,
|
42
|
+
feedback: false,
|
43
|
+
label: false,
|
96
44
|
value: value,
|
97
|
-
|
98
|
-
|
99
|
-
data: {'column-name' => name, 'column-index' => opts[:index]}
|
100
|
-
}.delete_if { |k, v| v.blank? && k != :name }
|
45
|
+
data: { 'column-name': name, 'column-index': opts[:index] }
|
46
|
+
)
|
101
47
|
|
102
|
-
case
|
48
|
+
case options.delete(:as)
|
103
49
|
when :string, :text, :number
|
104
|
-
form.
|
105
|
-
as: :string,
|
106
|
-
placeholder: placeholder,
|
107
|
-
wrapper_html: wrapper_html,
|
108
|
-
input_html: input_html
|
109
|
-
when :effective_obfuscation
|
110
|
-
input_html[:pattern] ||= '[0-9]{3}-?[0-9]{4}-?[0-9]{3}'
|
111
|
-
input_html[:title] = 'Expected format: XXX-XXXX-XXX'
|
112
|
-
|
113
|
-
form.input name, label: false, required: false, value: value,
|
114
|
-
as: :string,
|
115
|
-
placeholder: placeholder,
|
116
|
-
wrapper_html: wrapper_html,
|
117
|
-
input_html: input_html
|
50
|
+
form.text_field name, options
|
118
51
|
when :date, :datetime
|
119
|
-
form.
|
120
|
-
|
121
|
-
|
122
|
-
wrapper_html: wrapper_html,
|
123
|
-
input_group: false,
|
124
|
-
input_html: input_html,
|
125
|
-
date_linked: false,
|
126
|
-
input_js: { useStrict: true, keepInvalid: true }
|
127
|
-
# Keep invalid format like "2015-11" so we can still search by year, month or day
|
52
|
+
form.date_field name, options.reverse_merge(
|
53
|
+
date_linked: false, prepend: false, input_js: { useStrict: true, keepInvalid: true }
|
54
|
+
)
|
128
55
|
when :time
|
129
|
-
form.
|
130
|
-
|
131
|
-
|
132
|
-
wrapper_html: wrapper_html,
|
133
|
-
input_group: false,
|
134
|
-
input_html: input_html,
|
135
|
-
date_linked: false,
|
136
|
-
input_js: { useStrict: false, keepInvalid: true }
|
56
|
+
form.time_field name, options.reverse_merge(
|
57
|
+
date_linked: false, prepend: false, input_js: { useStrict: false, keepInvalid: true }
|
58
|
+
)
|
137
59
|
when :select, :boolean
|
138
|
-
|
139
|
-
|
140
|
-
collection: collection,
|
141
|
-
selected: opts[:search][:value],
|
142
|
-
multiple: opts[:search][:multiple],
|
143
|
-
grouped: opts[:search][:grouped],
|
144
|
-
polymorphic: opts[:search][:polymorphic],
|
145
|
-
template: opts[:search][:template],
|
146
|
-
include_blank: include_blank,
|
147
|
-
wrapper_html: wrapper_html,
|
148
|
-
input_html: input_html,
|
149
|
-
input_js: { placeholder: placeholder }
|
60
|
+
options[:input_js] = (options[:input_js] || {}).reverse_merge(placeholder: '')
|
61
|
+
form.select name, collection, options
|
150
62
|
when :bulk_actions
|
151
|
-
|
152
|
-
|
153
|
-
form.input name, label: false, required: false, value: nil,
|
154
|
-
as: :boolean,
|
155
|
-
input_html: input_html
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def render_datatable_filters(datatable)
|
160
|
-
raise 'expected datatable to be present' unless datatable
|
161
|
-
|
162
|
-
datatable.view ||= self
|
163
|
-
return unless datatable._scopes.present? || datatable._filters.present?
|
164
|
-
|
165
|
-
if datatable._filters_form_required?
|
166
|
-
render partial: 'effective/datatables/filters', locals: { datatable: datatable }
|
167
|
-
else
|
168
|
-
render(partial: 'effective/datatables/filters', locals: { datatable: datatable }).gsub('<form', '<div').gsub('/form>', '/div>').html_safe
|
63
|
+
options[:data]['role'] = 'bulk-actions-all'
|
64
|
+
form.check_box name, options.merge(custom: false)
|
169
65
|
end
|
170
|
-
|
171
66
|
end
|
172
67
|
|
173
68
|
def datatable_filter_tag(form, datatable, name, opts)
|
174
|
-
|
69
|
+
placeholder = opts.delete(:label)
|
70
|
+
|
71
|
+
collection = opts.delete(:collection)
|
175
72
|
value = datatable.state[:filter][name]
|
176
|
-
collection = opts[:collection]
|
177
|
-
input_html = opts[:input_html] || {}
|
178
73
|
|
179
|
-
|
74
|
+
options = opts.except(:parse).merge(
|
75
|
+
placeholder: placeholder,
|
76
|
+
feedback: false,
|
77
|
+
label: false,
|
180
78
|
value: value,
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
label: opts[:label],
|
185
|
-
required: input_html.delete(:required) || opts[:required],
|
186
|
-
multiple: input_html.delete(:multiple) || opts[:multiple],
|
187
|
-
include_blank: input_html.delete(:include_blank) || opts[:include_blank],
|
188
|
-
group_method: input_html.delete(:group_method),
|
189
|
-
group_label_method: input_html.delete(:group_label_method),
|
190
|
-
value_method: input_html.delete(:value_method),
|
191
|
-
label_method: input_html.delete(:label_method),
|
192
|
-
input_html: (({name: ''} unless datatable._filters_form_required?) || {}).merge(input_html),
|
193
|
-
input_js: ({ placeholder: ''} if as == :effective_select),
|
194
|
-
wrapper_html: {class: 'form-group-sm'}
|
195
|
-
}.compact
|
196
|
-
|
197
|
-
form.input name, **attributes
|
198
|
-
end
|
199
|
-
|
200
|
-
def datatable_scope_tag(form, datatable, opts = {})
|
201
|
-
collection = datatable._scopes.map { |name, opts| [opts[:label], name] }
|
202
|
-
value = datatable.state[:scope]
|
79
|
+
wrapper: { class: 'form-group col-auto'},
|
80
|
+
autocomplete: 'off'
|
81
|
+
)
|
203
82
|
|
204
|
-
|
205
|
-
as: (defined?(EffectiveFormInputs) ? :effective_radio_buttons : :radio_buttons),
|
206
|
-
collection: collection,
|
207
|
-
buttons: true,
|
208
|
-
wrapper_html: {class: 'btn-group-sm'}
|
209
|
-
end
|
210
|
-
|
211
|
-
def render_datatable_charts(datatable)
|
212
|
-
raise 'expected datatable to be present' unless datatable
|
213
|
-
|
214
|
-
datatable.view ||= self
|
215
|
-
return unless datatable._charts.present?
|
216
|
-
|
217
|
-
datatable._charts.map { |name, _| render_datatable_chart(datatable, name) }.join.html_safe
|
218
|
-
end
|
219
|
-
|
220
|
-
def render_datatable_chart(datatable, name)
|
221
|
-
raise 'expected datatable to be present' unless datatable
|
83
|
+
options[:name] = '' unless datatable._filters_form_required?
|
222
84
|
|
223
|
-
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
85
|
+
case options.delete(:as)
|
86
|
+
when :date
|
87
|
+
form.date_field name, options
|
88
|
+
when :datetime
|
89
|
+
form.datetime_field name, options
|
90
|
+
when :time
|
91
|
+
form.time_field name, options
|
92
|
+
when :select, :boolean
|
93
|
+
options[:input_js] = (options[:input_js] || {}).reverse_merge(placeholder: placeholder)
|
94
|
+
form.select name, collection, options
|
95
|
+
else
|
96
|
+
form.text_field name, options
|
97
|
+
end
|
230
98
|
end
|
231
99
|
|
232
100
|
end
|
@@ -1,7 +1,7 @@
|
|
1
1
|
module Effective
|
2
2
|
class Datatable
|
3
3
|
attr_reader :attributes # Anything that we initialize our table with. That's it. Can't be changed by state.
|
4
|
-
attr_reader :
|
4
|
+
attr_reader :resource
|
5
5
|
attr_reader :state
|
6
6
|
|
7
7
|
# Hashes of DSL options
|
@@ -15,8 +15,6 @@ module Effective
|
|
15
15
|
|
16
16
|
# The collection itself. Only evaluated once.
|
17
17
|
attr_accessor :_collection
|
18
|
-
attr_accessor :_collection_apply_belongs_to
|
19
|
-
attr_accessor :_collection_apply_scope
|
20
18
|
|
21
19
|
# The view
|
22
20
|
attr_reader :view
|
@@ -33,10 +31,10 @@ module Effective
|
|
33
31
|
include Effective::EffectiveDatatable::Resource
|
34
32
|
include Effective::EffectiveDatatable::State
|
35
33
|
|
36
|
-
def initialize(view = nil, attributes =
|
34
|
+
def initialize(view = nil, attributes = {})
|
37
35
|
(attributes = view; view = nil) if view.kind_of?(Hash)
|
38
36
|
|
39
|
-
@attributes = (attributes
|
37
|
+
@attributes = initial_attributes(attributes)
|
40
38
|
@state = initial_state
|
41
39
|
|
42
40
|
@_aggregates = {}
|
@@ -47,7 +45,6 @@ module Effective
|
|
47
45
|
@_form = {}
|
48
46
|
@_scopes = {}
|
49
47
|
|
50
|
-
raise 'expected a hash of arguments' unless @attributes.kind_of?(Hash)
|
51
48
|
raise 'collection is defined as a method. Please use the collection do ... end syntax.' unless collection.nil?
|
52
49
|
self.view = view if view
|
53
50
|
end
|
@@ -57,23 +54,21 @@ module Effective
|
|
57
54
|
@view = (view.respond_to?(:view_context) ? view.view_context : view)
|
58
55
|
raise 'expected view to respond to params' unless @view.respond_to?(:params)
|
59
56
|
|
60
|
-
|
57
|
+
load_cookie!
|
61
58
|
load_attributes!
|
62
59
|
|
63
60
|
# We need early access to filter and scope, to define defaults from the model first
|
64
|
-
# This means filters do
|
61
|
+
# This means filters do knows about attributes but not about columns.
|
65
62
|
initialize_filters if respond_to?(:initialize_filters)
|
66
63
|
load_filters!
|
67
64
|
load_state!
|
68
65
|
|
69
|
-
# Bulk actions called first so it can add the bulk_actions_col first
|
70
|
-
initialize_bulk_actions if respond_to?(:initialize_bulk_actions)
|
71
|
-
|
72
66
|
# Now we initialize all the columns. columns knows about attributes and filters and scope
|
73
67
|
initialize_datatable if respond_to?(:initialize_datatable)
|
74
68
|
load_columns!
|
75
69
|
|
76
70
|
# Execute any additional DSL methods
|
71
|
+
initialize_bulk_actions if respond_to?(:initialize_bulk_actions)
|
77
72
|
initialize_charts if respond_to?(:initialize_charts)
|
78
73
|
|
79
74
|
# Load the collection. This is the first time def collection is called on the Datatable itself
|
@@ -83,10 +78,9 @@ module Effective
|
|
83
78
|
# Figure out the class, and if it's activerecord, do all the resource discovery on it
|
84
79
|
load_resource!
|
85
80
|
|
86
|
-
#
|
87
|
-
|
81
|
+
# If attributes match a belongs_to column, scope the collection and remove the column
|
82
|
+
apply_belongs_to_attributes!
|
88
83
|
|
89
|
-
# Save for next time
|
90
84
|
save_cookie!
|
91
85
|
end
|
92
86
|
|
@@ -123,18 +117,11 @@ module Effective
|
|
123
117
|
)
|
124
118
|
end
|
125
119
|
|
126
|
-
#
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
# Reordering
|
132
|
-
def reorder?
|
133
|
-
columns.key?(:_reorder)
|
134
|
-
end
|
135
|
-
|
136
|
-
def sortable?
|
137
|
-
!reorder? && attributes[:sortable] != false
|
120
|
+
# When simple only a table will be rendered with
|
121
|
+
# no sorting, no filtering, no export buttons, no pagination, no per page, no colReorder
|
122
|
+
# default sorting only, default visibility only, all records returned, and responsive enabled
|
123
|
+
def simple?
|
124
|
+
attributes[:simple] == true
|
138
125
|
end
|
139
126
|
|
140
127
|
# Whether the filters must be rendered as a <form> or we can keep the normal <div> behaviour
|
@@ -142,12 +129,12 @@ module Effective
|
|
142
129
|
_form[:verb].present?
|
143
130
|
end
|
144
131
|
|
145
|
-
def
|
146
|
-
|
132
|
+
def table_html_class
|
133
|
+
attributes[:class] || EffectiveDatatables.html_class
|
147
134
|
end
|
148
135
|
|
149
136
|
def to_param
|
150
|
-
"#{self.class.name.underscore.parameterize}-#{
|
137
|
+
@to_param ||= "#{self.class.name.underscore.parameterize}-#{cookie_param}"
|
151
138
|
end
|
152
139
|
|
153
140
|
def columns
|
@@ -162,14 +149,6 @@ module Effective
|
|
162
149
|
@dsl_tool ||= DatatableDslTool.new(self)
|
163
150
|
end
|
164
151
|
|
165
|
-
def resource
|
166
|
-
raise('depecated. Please use .effective_resource instead')
|
167
|
-
end
|
168
|
-
|
169
|
-
def fallback_effective_resource
|
170
|
-
@fallback_effective_resource ||= Effective::Resource.new('', namespace: controller_namespace)
|
171
|
-
end
|
172
|
-
|
173
152
|
private
|
174
153
|
|
175
154
|
def column_tool
|
@@ -180,12 +159,5 @@ module Effective
|
|
180
159
|
@value_tool ||= DatatableValueTool.new(self)
|
181
160
|
end
|
182
161
|
|
183
|
-
def validate_datatable!
|
184
|
-
if reorder?
|
185
|
-
raise 'cannot use reorder with an Array collection' unless active_record_collection?
|
186
|
-
raise 'cannot use reorder with a non-Integer column' if effective_resource.sql_type(columns[:_reorder][:reorder]) != :integer
|
187
|
-
end
|
188
|
-
end
|
189
|
-
|
190
162
|
end
|
191
163
|
end
|
@@ -43,7 +43,7 @@ module Effective
|
|
43
43
|
Rails.logger.info "COLUMN TOOL: order_column #{column.to_s} #{direction} #{sql_column}" if EffectiveDatatables.debug
|
44
44
|
|
45
45
|
if column[:sql_as_column]
|
46
|
-
collection.order("#{sql_column} #{datatable.
|
46
|
+
collection.order("#{sql_column} #{datatable.resource.sql_direction(direction)}")
|
47
47
|
else
|
48
48
|
Effective::Resource.new(collection)
|
49
49
|
.order(column[:name], direction, as: column[:as], sort: column[:sort], sql_column: column[:sql_column], limit: datatable.limit)
|
@@ -75,10 +75,8 @@ module Effective
|
|
75
75
|
def search_column(collection, value, column, sql_column)
|
76
76
|
Rails.logger.info "COLUMN TOOL: search_column #{column.to_s} #{value} #{sql_column}" if EffectiveDatatables.debug
|
77
77
|
|
78
|
-
operation = (column[:search][:fuzzy] && column[:as] == :string) ? :matches : :eq
|
79
|
-
|
80
78
|
Effective::Resource.new(collection)
|
81
|
-
.search(column[:name], value, as: column[:as],
|
79
|
+
.search(column[:name], value, as: column[:as], fuzzy: column[:search][:fuzzy], sql_column: sql_column)
|
82
80
|
end
|
83
81
|
|
84
82
|
def paginate(collection)
|
@@ -16,24 +16,16 @@ module Effective
|
|
16
16
|
@view = datatable.view
|
17
17
|
end
|
18
18
|
|
19
|
-
def method_missing(method, *args
|
19
|
+
def method_missing(method, *args)
|
20
20
|
# Catch a common error
|
21
21
|
if [:bulk_actions, :charts, :collection, :filters].include?(method) && in_datatables_do_block
|
22
22
|
raise "#{method} block must be declared outside the datatable do ... end block"
|
23
23
|
end
|
24
24
|
|
25
25
|
if datatable.respond_to?(method)
|
26
|
-
|
27
|
-
datatable.send(method, *args) { yield }
|
28
|
-
else
|
29
|
-
datatable.send(method, *args)
|
30
|
-
end
|
26
|
+
datatable.send(method, *args)
|
31
27
|
elsif view.respond_to?(method)
|
32
|
-
|
33
|
-
view.send(method, *args) { yield }
|
34
|
-
else
|
35
|
-
view.send(method, *args)
|
36
|
-
end
|
28
|
+
view.send(method, *args)
|
37
29
|
else
|
38
30
|
super
|
39
31
|
end
|
@@ -74,12 +74,13 @@ module Effective
|
|
74
74
|
collection
|
75
75
|
end
|
76
76
|
|
77
|
-
def search_column(collection,
|
78
|
-
Rails.logger.info "VALUE TOOL: search_column #{column.to_s} #{
|
77
|
+
def search_column(collection, value, column, index)
|
78
|
+
Rails.logger.info "VALUE TOOL: search_column #{column.to_s} #{value} #{index}" if EffectiveDatatables.debug
|
79
79
|
|
80
|
+
macros = Effective::Resource.new('').macros
|
80
81
|
fuzzy = column[:search][:fuzzy]
|
81
82
|
|
82
|
-
term = Effective::Attribute.new(column[:as]).parse(
|
83
|
+
term = Effective::Attribute.new(column[:as]).parse(value, name: column[:name])
|
83
84
|
term_downcased = term.to_s.downcase
|
84
85
|
|
85
86
|
# term == 'nil' rescue false is a Rails 4.1 fix, where you can't compare a TimeWithZone to 'nil'
|
@@ -89,19 +90,18 @@ module Effective
|
|
89
90
|
|
90
91
|
# See effective_resources gem search() method # relation.rb
|
91
92
|
collection.select! do |row|
|
92
|
-
obj = row[index]
|
93
|
-
value = obj_to_value(row[index], column, row)
|
93
|
+
obj = obj_to_value(row[index], column, row)
|
94
94
|
|
95
95
|
case column[:as]
|
96
96
|
when :boolean
|
97
|
-
if
|
98
|
-
|
97
|
+
if fuzzy
|
98
|
+
term ? (obj == true) : (obj != true)
|
99
99
|
else
|
100
|
-
|
100
|
+
obj == term
|
101
101
|
end
|
102
102
|
when :datetime, :date
|
103
103
|
end_at = (
|
104
|
-
case (
|
104
|
+
case (value.to_s.scan(/(\d+)/).flatten).length
|
105
105
|
when 1 ; term.end_of_year # Year
|
106
106
|
when 2 ; term.end_of_month # Year-Month
|
107
107
|
when 3 ; term.end_of_day # Year-Month-Day
|
@@ -111,35 +111,35 @@ module Effective
|
|
111
111
|
else term
|
112
112
|
end
|
113
113
|
)
|
114
|
-
|
114
|
+
obj >= term && obj <= end_at
|
115
115
|
when :time
|
116
|
-
(
|
116
|
+
(obj.hour == term.hour) && (term.min == 0 ? true : (obj.min == term.min))
|
117
117
|
when :decimal, :currency
|
118
|
-
if fuzzy && (term.round(0) == term) &&
|
118
|
+
if fuzzy && (term.round(0) == term) && value.to_s.include?('.') == false
|
119
119
|
if term < 0
|
120
|
-
|
120
|
+
obj <= term && obj > (term - 1.0)
|
121
121
|
else
|
122
|
-
|
122
|
+
obj >= term && obj < (term + 1.0)
|
123
123
|
end
|
124
124
|
else
|
125
|
-
|
125
|
+
obj == term
|
126
126
|
end
|
127
127
|
when :duration
|
128
|
-
if fuzzy && (term % 60 == 0) &&
|
128
|
+
if fuzzy && (term % 60 == 0) && value.to_s.include?('m') == false
|
129
129
|
if term < 0
|
130
|
-
|
130
|
+
obj <= term && obj > (term - 60)
|
131
131
|
else
|
132
|
-
|
132
|
+
obj >= term && obj < (term + 60)
|
133
133
|
end
|
134
134
|
else
|
135
|
-
|
135
|
+
obj == term
|
136
136
|
end
|
137
|
-
when *
|
137
|
+
when *macros, :resource
|
138
138
|
Array(obj).any? do |resource|
|
139
139
|
Array(term).any? do |term|
|
140
140
|
matched = false
|
141
141
|
|
142
|
-
if term.kind_of?(Integer) && resource.respond_to?(:
|
142
|
+
if term.kind_of?(Integer) && resource.respond_to?(:to_param)
|
143
143
|
matched = (resource.id == term || resource.to_param == term)
|
144
144
|
end
|
145
145
|
|
@@ -148,9 +148,9 @@ module Effective
|
|
148
148
|
end
|
149
149
|
else # :string, :text, :email
|
150
150
|
if fuzzy
|
151
|
-
|
151
|
+
obj.to_s.downcase.include?(term_downcased)
|
152
152
|
else
|
153
|
-
|
153
|
+
obj == term || (obj.to_s == term.to_s)
|
154
154
|
end
|
155
155
|
end
|
156
156
|
end || collection
|
@@ -4,14 +4,22 @@ module Effective
|
|
4
4
|
|
5
5
|
private
|
6
6
|
|
7
|
-
def
|
8
|
-
|
9
|
-
|
10
|
-
end
|
7
|
+
def initial_attributes(args)
|
8
|
+
raise "#{self.class.name}.new() expected Hash like arguments" unless args.kind_of?(Hash)
|
9
|
+
args
|
11
10
|
end
|
12
11
|
|
13
12
|
def load_attributes!
|
14
|
-
|
13
|
+
if datatables_ajax_request?
|
14
|
+
raise 'expected cookie to be present' unless cookie
|
15
|
+
raise 'expected attributes cookie to be present' unless cookie[:attributes]
|
16
|
+
|
17
|
+
@attributes = cookie.delete(:attributes)
|
18
|
+
end
|
19
|
+
|
20
|
+
unless datatables_ajax_request?
|
21
|
+
@attributes[:_n] ||= view.controller_path.split('/')[0...-1].join('/').presence
|
22
|
+
end
|
15
23
|
end
|
16
24
|
|
17
25
|
end
|
@@ -7,23 +7,10 @@ module Effective
|
|
7
7
|
@collection_class # Will be either User/Post/etc or Array
|
8
8
|
end
|
9
9
|
|
10
|
-
# User.all
|
11
10
|
def active_record_collection?
|
12
11
|
@active_record_collection == true
|
13
12
|
end
|
14
13
|
|
15
|
-
# [User<1>, User<2>, Post<1>, Page<3>]
|
16
|
-
def active_record_array_collection?
|
17
|
-
@active_record_array_collection == true
|
18
|
-
end
|
19
|
-
|
20
|
-
def active_record_polymorphic_array_collection?
|
21
|
-
return false unless active_record_array_collection?
|
22
|
-
return @active_record_polymorphic_array_collection unless @active_record_polymorphic_array_collection.nil?
|
23
|
-
@active_record_polymorphic_array_collection = collection.map { |obj| obj.class }.uniq.length > 1
|
24
|
-
end
|
25
|
-
|
26
|
-
# [[1, 'foo'], [2, 'bar']]
|
27
14
|
def array_collection?
|
28
15
|
@array_collection == true
|
29
16
|
end
|
@@ -34,13 +21,11 @@ module Effective
|
|
34
21
|
raise 'No collection defined. Please add a collection with collection do ... end' if collection.nil?
|
35
22
|
|
36
23
|
@collection_class = (collection.respond_to?(:klass) ? collection.klass : self.class)
|
37
|
-
|
38
24
|
@active_record_collection = (collection.ancestors.include?(ActiveRecord::Base) rescue false)
|
39
|
-
@
|
40
|
-
@array_collection = collection.kind_of?(Array) && (collection.blank? || collection.first.kind_of?(Array))
|
25
|
+
@array_collection = (collection.kind_of?(Array) && (collection.length == 0 || collection.first.kind_of?(Array)))
|
41
26
|
|
42
|
-
unless active_record_collection? ||
|
43
|
-
raise "Unsupported collection. Expecting an ActiveRecord
|
27
|
+
unless active_record_collection? || array_collection?
|
28
|
+
raise "Unsupported collection type. Expecting an ActiveRecord class, ActiveRecord relation, or an Array of Arrays [[1, 'foo'], [2, 'bar']]"
|
44
29
|
end
|
45
30
|
|
46
31
|
_scopes.each do |scope, _|
|