effective_datatables 3.7.10 → 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/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, _|
|