effective_datatables 4.8.4 → 4.8.9

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 53f857de2d8388bada0837e3eca598ab75e45cba907bde7b43c01a13c2037cb1
4
- data.tar.gz: '0488a5bf9fafd8a54833615f6d7610d22567d97c5e1b0d13cd2476e24706d08b'
3
+ metadata.gz: da2dfe401e2839d034033b2af1b0048cf3c6a726b87a1f6ccc4354eb71183f55
4
+ data.tar.gz: b6c6a44db10ce020e32bd79de4f1dc8a77106122f7725524414e0ccfa2ee4265
5
5
  SHA512:
6
- metadata.gz: 740d034417e5aa04860b12a308f4e495b3856c4b86a67443f6ec2e18900a55be58c6edb7235d8ef66981bb827f05ecab29d3f691765b5dee43f5312804644adf
7
- data.tar.gz: 91712a50aff213013867fd46bbdedc717e0c95fef1748d2d9076bfdd5930ce14a3fff1d158f0feed409c8431fb16b317fae1c34b21accd855546dc089c9dbb0d
6
+ metadata.gz: 75201440e6f62b181ebce2f54dbaedcffae413a42803e1b0e39a7869f8425e776d51b10b88c2625d142a89895eb6f4ab3f174715782bdb068c5958908b0e36a3
7
+ data.tar.gz: b9442dab7b1f1b7a1b34e39ec1b67e3241757b1978272ea051c01cf77a9ae074b1ccac33aa18cc52a84a1f735697b41c72fba970a1d39a0c1a734d40c17f125c
data/README.md CHANGED
@@ -1155,6 +1155,22 @@ def finalize(collection)
1155
1155
  end
1156
1156
  ```
1157
1157
 
1158
+ ## Render outside of view
1159
+
1160
+ You can render a datatable outside the view.
1161
+
1162
+ Anything you pass to the `rendered` method is treated as view/request params.
1163
+
1164
+ You can test filters and scopes by passing them here.
1165
+
1166
+ ```
1167
+ post = Post.create!
1168
+ datatable = PostsDatatable.new.rendered(end_date: Time.zone.now+2.days, current_user_id: 1)
1169
+
1170
+ assert_equal 1, datatable.collection.count
1171
+ assert_equal [post], datatable.collection
1172
+ ```
1173
+
1158
1174
  ## Authorization
1159
1175
 
1160
1176
  All authorization checks are handled via the config.authorization_method found in the `config/initializers/effective_datatables.rb` file.
@@ -175,7 +175,9 @@ initializeDataTables = (target) ->
175
175
 
176
176
  value = $input.val()
177
177
 
178
- if value.startsWith('"') && value.endsWith('"')
178
+ if Array.isArray(value)
179
+ # Nothing
180
+ else if value.startsWith('"') && value.endsWith('"')
179
181
  value = value.substring(1, value.length-1)
180
182
  else
181
183
  value = $.trim(value)
@@ -1,15 +1,34 @@
1
1
  # To achieve inline crud, we use rails' data-remote links, and override their behaviour when inside a datatable
2
2
  # This works with EffectiveForm.remote_form which is part of the effective_bootstrap gem.
3
3
 
4
- # We click the New/Edit/Action button from the col-actions
5
- $(document).on 'ajax:beforeSend', '.dataTables_wrapper .col-actions', (e, xhr, settings) ->
6
- $action = $(e.target)
7
- $table = $(e.target).closest('table')
4
+ # https://github.com/rails/jquery-ujs/wiki/ajax
5
+ # https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
6
+
7
+ $(document).on 'ajax:before', '.dataTables_wrapper .col-actions', (event) ->
8
+ $action = $(event.target)
9
+ $table = $(event.target).closest('table')
8
10
 
9
11
  return true if ('' + $action.data('inline')) == 'false'
10
12
 
11
- $params = $.param({_datatable_id: $table.attr('id'), _datatable_attributes: $table.data('attributes'), _datatable_action: true })
12
- settings.url += (if settings.url.indexOf('?') == -1 then '?' else '&') + $params
13
+ $params = $.param(
14
+ {
15
+ _datatable_id: $table.attr('id'),
16
+ _datatable_attributes: $table.data('attributes'),
17
+ _datatable_action: true
18
+ }
19
+ )
20
+
21
+ $action.attr('data-params', $params)
22
+ true
23
+
24
+ # We click the New/Edit/Action button from the col-actions
25
+ $(document).on 'ajax:beforeSend', '.dataTables_wrapper .col-actions', (event, xhr, settings) ->
26
+ [xhr, settings] = event.detail if event.detail # rails/ujs
27
+
28
+ $action = $(event.target)
29
+ $table = $(event.target).closest('table')
30
+
31
+ return true if ('' + $action.data('inline')) == 'false'
13
32
 
14
33
  if $action.closest('.effective-datatables-inline-row,table.dataTable').hasClass('effective-datatables-inline-row')
15
34
  # Nothing.
@@ -22,6 +41,8 @@ $(document).on 'ajax:beforeSend', '.dataTables_wrapper .col-actions', (e, xhr, s
22
41
 
23
42
  # We have either completed the resource action, or fetched the inline form to load.
24
43
  $(document).on 'ajax:success', '.dataTables_wrapper .col-actions', (event, data) ->
44
+ [data, status, xhr] = event.detail if event.detail # rails/ujs
45
+
25
46
  $action = $(event.target)
26
47
 
27
48
  return true if ('' + $action.data('inline')) == 'false'
@@ -54,12 +75,22 @@ $(document).on 'ajax:error', '.dataTables_wrapper', (event) ->
54
75
  EffectiveForm.remote_form_flash = ''
55
76
  true
56
77
 
57
- # Submitting an inline datatables form
58
- $(document).on 'ajax:beforeSend', '.dataTables_wrapper .col-inline-form', (e, xhr, settings) ->
59
- $table = $(e.target).closest('table')
78
+ ## Now for the fetched form. We add the datatables params attributes
79
+
80
+ $(document).on 'ajax:before', '.dataTables_wrapper .col-inline-form', (event) ->
81
+ $action = $(event.target)
82
+ $form = $action.closest('form')
83
+ $table = $action.closest('table')
84
+
85
+ if $form.find('input[name=_datatable_id]').length == 0
86
+ $('<input>').attr(
87
+ {type: 'hidden', name: '_datatable_id', value: $table.attr('id')}
88
+ ).appendTo($form)
60
89
 
61
- $params = $.param({_datatable_id: $table.attr('id'), _datatable_attributes: $table.data('attributes') })
62
- settings.url += (if settings.url.indexOf('?') == -1 then '?' else '&') + $params
90
+ if $form.find('input[name=_datatable_attributes]').length == 0
91
+ $('<input>').attr(
92
+ {type: 'hidden', name: '_datatable_attributes', value: $table.data('attributes')}
93
+ ).appendTo($form)
63
94
 
64
95
  true
65
96
 
@@ -44,7 +44,7 @@ module EffectiveDatatablesPrivateHelper
44
44
  action = { action: :new, class: ['btn', column[:btn_class].presence].compact.join(' '), 'data-remote': true }
45
45
 
46
46
  if column[:actions][:new].kind_of?(Hash) # This might be active_record_array_collection?
47
- action = action.merge(column[:actions][:new])
47
+ action.merge!(column[:actions][:new])
48
48
 
49
49
  effective_resource = (datatable.effective_resource || datatable.fallback_effective_resource)
50
50
  klass = (column[:actions][:new][:klass] || effective_resource&.klass || datatable.collection_class)
@@ -84,7 +84,7 @@ module EffectiveDatatablesPrivateHelper
84
84
  collection = opts[:search].delete(:collection)
85
85
  value = datatable.state[:search][name]
86
86
 
87
- options = opts[:search].except(:fuzzy).merge!(
87
+ options = opts[:search].merge!(
88
88
  name: nil,
89
89
  feedback: false,
90
90
  label: false,
@@ -92,24 +92,26 @@ module EffectiveDatatablesPrivateHelper
92
92
  data: { 'column-name': name, 'column-index': opts[:index] }
93
93
  )
94
94
 
95
+ options.delete(:fuzzy)
96
+
95
97
  case options.delete(:as)
96
98
  when :string, :text, :number
97
99
  form.text_field name, options
98
100
  when :date, :datetime
99
- form.date_field name, options.reverse_merge(
101
+ form.date_field name, options.reverse_merge!(
100
102
  date_linked: false, prepend: false, input_js: { useStrict: true, keepInvalid: true }
101
103
  )
102
104
  when :time
103
- form.time_field name, options.reverse_merge(
105
+ form.time_field name, options.reverse_merge!(
104
106
  date_linked: false, prepend: false, input_js: { useStrict: false, keepInvalid: true }
105
107
  )
106
108
  when :select, :boolean
107
- options[:input_js] = (options[:input_js] || {}).reverse_merge(placeholder: '')
109
+ options[:input_js] = (options[:input_js] || {}).reverse_merge!(placeholder: '')
108
110
 
109
111
  form.select name, collection, options
110
112
  when :bulk_actions
111
113
  options[:data]['role'] = 'bulk-actions'
112
- form.check_box name, options.merge(label: '&nbsp;')
114
+ form.check_box name, options.merge!(label: '&nbsp;')
113
115
  end
114
116
  end
115
117
 
@@ -139,7 +141,7 @@ module EffectiveDatatablesPrivateHelper
139
141
  placeholder: (opts[:label] || name.to_s.titleize),
140
142
  value: value,
141
143
  wrapper: { class: 'form-group col-auto'}
142
- }.merge(opts.except(:as, :collection, :parse, :value))
144
+ }.merge!(opts.except(:as, :collection, :parse, :value))
143
145
 
144
146
  options[:name] = '' unless datatable._filters_form_required?
145
147
 
@@ -171,7 +173,7 @@ module EffectiveDatatablesPrivateHelper
171
173
  label: false,
172
174
  required: false,
173
175
  wrapper: { class: 'form-group col-auto'}
174
- }.merge(opts.except(:checked, :value))
176
+ }.merge!(opts.except(:checked, :value))
175
177
 
176
178
  form.radios :scope, collection, options
177
179
  end
@@ -53,10 +53,36 @@ module Effective
53
53
  self.view = view if view
54
54
  end
55
55
 
56
+ def rendered(params = {})
57
+ raise('expected a hash of params') unless params.kind_of?(Hash)
58
+
59
+ view = ApplicationController.renderer.controller.helpers
60
+
61
+ view.class_eval do
62
+ attr_accessor :rendered_params
63
+
64
+ def current_user
65
+ rendered_params[:current_user]
66
+ end
67
+ end
68
+
69
+ if params[:current_user_id]
70
+ params[:current_user] = User.find(params[:current_user_id])
71
+ end
72
+
73
+ view.rendered_params = params
74
+
75
+ self.view = view
76
+ self
77
+ end
78
+
56
79
  # Once the view is assigned, we initialize everything
57
80
  def view=(view)
58
81
  @view = (view.respond_to?(:view_context) ? view.view_context : view)
59
- raise 'expected view to respond to params' unless @view.respond_to?(:params)
82
+
83
+ unless @view.respond_to?(:params) || @view.respond_to?(:rendered_params)
84
+ raise 'expected view to respond to params'
85
+ end
60
86
 
61
87
  assert_attributes!
62
88
  load_attributes!
@@ -11,6 +11,7 @@ module Effective
11
11
  end
12
12
 
13
13
  def load_attributes!
14
+ return unless view.respond_to?(:controller_path)
14
15
  @attributes[:namespace] ||= view.controller_path.split('/')[0...-1].join('/')
15
16
  end
16
17
 
@@ -64,6 +64,7 @@ module Effective
64
64
  if state[:visible][name] == false && (name != order_name) # Sort by invisible array column
65
65
  BLANK
66
66
  elsif opts[:compute]
67
+
67
68
  if array_collection?
68
69
  dsl_tool.instance_exec(obj, obj[opts[:index]], &opts[:compute])
69
70
  else
@@ -10,6 +10,7 @@ module Effective
10
10
 
11
11
  def load_cookie!
12
12
  return unless EffectiveDatatables.save_state
13
+ return unless view.respond_to?(:cookies)
13
14
 
14
15
  @dt_cookie = view.cookies.signed['_effective_dt']
15
16
 
@@ -33,6 +34,7 @@ module Effective
33
34
 
34
35
  def save_cookie!
35
36
  return unless EffectiveDatatables.save_state
37
+ return unless view.respond_to?(:cookies)
36
38
 
37
39
  @dt_cookie ||= []
38
40
  @dt_cookie << [cookie_key, cookie_payload]
@@ -16,7 +16,7 @@ module Effective
16
16
  next unless state[:visible][name]
17
17
 
18
18
  if opts[:partial]
19
- locals = { datatable: self, column: opts }.merge(resource_col_locals(opts))
19
+ locals = { datatable: self, column: opts }.merge!(resource_col_locals(opts))
20
20
 
21
21
  rendered[name] = (view.render(
22
22
  partial: opts[:partial],
@@ -27,7 +27,6 @@ module Effective
27
27
  spacer_template: SPACER_TEMPLATE
28
28
  ) || '').split(SPACER)
29
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
30
  locals = { datatable: self, column: opts, spacer_template: SPACER_TEMPLATE }
32
31
 
33
32
  atts = {
@@ -36,16 +35,17 @@ module Effective
36
35
  effective_resource: effective_resource,
37
36
  locals: locals,
38
37
  partial: opts[:actions_partial],
39
- }.compact.merge(opts[:actions])
38
+ }.merge!(opts[:actions]).tap(&:compact!)
40
39
 
41
40
  rendered[name] = if effective_resource.blank?
42
- resources.map do |resource|
41
+ collection.map { |row| row[opts[:index]] }.map do |resource|
43
42
  polymorphic_resource = Effective::Resource.new(resource, namespace: controller_namespace)
44
43
  (view.render_resource_actions(resource, atts.merge(effective_resource: polymorphic_resource), &opts[:format]) || '')
45
44
  end
46
45
  else
47
- (view.render_resource_actions(resources, atts, &opts[:format]) || '').split(SPACER)
46
+ (view.render_resource_actions(collection.map { |row| row[opts[:index]] }, atts, &opts[:format]) || '').split(SPACER)
48
47
  end
48
+
49
49
  end
50
50
  end
51
51
 
@@ -135,7 +135,7 @@ module Effective
135
135
  end
136
136
 
137
137
  # Merge local options. Special behaviour for remote: false
138
- if column[:actions].kind_of?(Hash) && column[:actions].present?
138
+ if column[:actions].present? && column[:actions].kind_of?(Hash)
139
139
  column[:actions].each do |action, opts|
140
140
  next unless opts.kind_of?(Hash)
141
141
 
@@ -6,18 +6,23 @@ module Effective
6
6
 
7
7
  def datatables_ajax_request?
8
8
  return @_datatables_ajax_request unless @_datatables_ajax_request.nil?
9
+ return unless view.respond_to?(:params)
9
10
 
10
11
  @_datatables_ajax_request = (view.present? && view.params.key?(:draw) && view.params.key?(:columns))
11
12
  end
12
13
 
13
14
  def datatables_inline_request?
14
15
  return @_datatables_inline_request unless @_datatables_inline_request.nil?
16
+ return unless view.respond_to?(:params)
15
17
 
16
18
  @_datatables_inline_request = (view.present? && view.params[:_datatable_id].to_s.split('-')[0...-1] == to_param.split('-')[0...-1])
17
19
  end
18
20
 
19
21
  def params
20
22
  return {} unless view.present?
23
+ return view.rendered_params if view.respond_to?(:rendered_params)
24
+ return {} unless view.respond_to?(:request)
25
+
21
26
  @params ||= {}.tap do |params|
22
27
  Rack::Utils.parse_query(URI(view.request.referer.presence || '/').query).each { |k, v| params[k.to_sym] = v }
23
28
  view.params.each { |k, v| params[k.to_sym] = v }
@@ -98,9 +98,11 @@ module Effective
98
98
  opts[:sql_as_column] = true if (effective_resource.table && effective_resource.column(name).blank?)
99
99
  end
100
100
 
101
- if opts[:sql_column].present? && AGGREGATE_SQL_FUNCTIONS.any? { |str| opts[:sql_column].to_s.start_with?(str) }
102
- opts[:sql_as_column] = true
101
+ if opts[:sql_column].present?
102
+ sql_column = opts[:sql_column].to_s
103
+ opts[:sql_as_column] = true if AGGREGATE_SQL_FUNCTIONS.any? { |str| sql_column.start_with?(str) }
103
104
  end
105
+
104
106
  end
105
107
  end
106
108
 
@@ -200,7 +202,7 @@ module Effective
200
202
 
201
203
  def load_resource_belongs_tos!
202
204
  return unless active_record_collection?
203
- return unless @_collection_apply_belongs_to
205
+ return unless @_collection_apply_belongs_to
204
206
 
205
207
  changed = attributes.select do |attribute, value|
206
208
  attribute = attribute.to_s
@@ -1,3 +1,3 @@
1
1
  module EffectiveDatatables
2
- VERSION = '4.8.4'.freeze
2
+ VERSION = '4.8.9'.freeze
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_datatables
3
3
  version: !ruby/object:Gem::Version
4
- version: 4.8.4
4
+ version: 4.8.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-15 00:00:00.000000000 Z
11
+ date: 2020-09-18 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -193,7 +193,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
193
  - !ruby/object:Gem::Version
194
194
  version: '0'
195
195
  requirements: []
196
- rubygems_version: 3.1.2
196
+ rubygems_version: 3.1.4
197
197
  signing_key:
198
198
  specification_version: 4
199
199
  summary: Uniquely powerful server-side searching, sorting and filtering of any ActiveRecord