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.
Files changed (68) hide show
  1. checksums.yaml +5 -5
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +32 -32
  4. data/app/assets/images/dataTables/sort-down.svg +1 -0
  5. data/app/assets/images/dataTables/sort-up.svg +1 -0
  6. data/app/assets/images/dataTables/sort.svg +1 -0
  7. data/app/assets/javascripts/dataTables/buttons/{buttons.bootstrap.js → buttons.bootstrap4.js} +7 -15
  8. data/app/assets/javascripts/dataTables/dataTables.bootstrap4.js +184 -0
  9. data/app/assets/javascripts/dataTables/responsive/dataTables.responsive.js +30 -11
  10. data/app/assets/javascripts/dataTables/responsive/{responsive.bootstrap.js → responsive.bootstrap4.js} +6 -6
  11. data/app/assets/javascripts/effective_datatables.js +4 -4
  12. data/app/assets/javascripts/effective_datatables/bulk_actions.js.coffee +43 -43
  13. data/app/assets/javascripts/effective_datatables/events.js.coffee +7 -4
  14. data/app/assets/javascripts/effective_datatables/filters.js.coffee +0 -1
  15. data/app/assets/javascripts/effective_datatables/initialize.js.coffee +45 -49
  16. data/app/assets/javascripts/effective_datatables/overrides.js +12 -0
  17. data/app/assets/javascripts/effective_datatables/reset.js.coffee +1 -1
  18. data/app/assets/stylesheets/dataTables/buttons/{buttons.bootstrap.scss → buttons.bootstrap4.css} +68 -1
  19. data/app/assets/stylesheets/dataTables/{dataTables.bootstrap.scss → dataTables.bootstrap4.css} +44 -29
  20. data/app/assets/stylesheets/dataTables/responsive/{responsive.bootstrap.scss → responsive.bootstrap4.css} +3 -3
  21. data/app/assets/stylesheets/effective_datatables.scss +3 -4
  22. data/app/assets/stylesheets/effective_datatables/_overrides.scss +72 -152
  23. data/app/controllers/effective/datatables_controller.rb +6 -39
  24. data/app/helpers/effective_datatables_helper.rb +55 -50
  25. data/app/helpers/effective_datatables_private_helper.rb +47 -179
  26. data/app/models/effective/datatable.rb +16 -44
  27. data/app/models/effective/datatable_column.rb +0 -1
  28. data/app/models/effective/datatable_column_tool.rb +1 -1
  29. data/app/models/effective/datatable_dsl_tool.rb +3 -11
  30. data/app/models/effective/datatable_value_tool.rb +23 -23
  31. data/app/models/effective/effective_datatable/attributes.rb +13 -5
  32. data/app/models/effective/effective_datatable/collection.rb +3 -18
  33. data/app/models/effective/effective_datatable/compute.rb +6 -17
  34. data/app/models/effective/effective_datatable/cookie.rb +20 -19
  35. data/app/models/effective/effective_datatable/dsl.rb +3 -8
  36. data/app/models/effective/effective_datatable/dsl/bulk_actions.rb +25 -14
  37. data/app/models/effective/effective_datatable/dsl/datatable.rb +28 -70
  38. data/app/models/effective/effective_datatable/dsl/filters.rb +5 -5
  39. data/app/models/effective/effective_datatable/format.rb +50 -95
  40. data/app/models/effective/effective_datatable/params.rb +3 -8
  41. data/app/models/effective/effective_datatable/resource.rb +76 -137
  42. data/app/models/effective/effective_datatable/state.rb +15 -30
  43. data/app/views/effective/datatables/_actions_column.html.haml +8 -1
  44. data/app/views/effective/datatables/_bulk_actions_column.html.haml +1 -1
  45. data/app/views/effective/datatables/_filters.html.haml +11 -12
  46. data/app/views/effective/datatables/_resource_column.html.haml +8 -11
  47. data/config/effective_datatables.rb +14 -12
  48. data/config/routes.rb +0 -1
  49. data/lib/effective_datatables.rb +4 -57
  50. data/lib/effective_datatables/engine.rb +1 -1
  51. data/lib/effective_datatables/version.rb +1 -1
  52. metadata +20 -30
  53. data/app/assets/images/dataTables/sort_asc.png +0 -0
  54. data/app/assets/images/dataTables/sort_both.png +0 -0
  55. data/app/assets/images/dataTables/sort_desc.png +0 -0
  56. data/app/assets/javascripts/dataTables/dataTables.bootstrap.js +0 -182
  57. data/app/assets/javascripts/dataTables/locales/en.lang +0 -33
  58. data/app/assets/javascripts/dataTables/locales/es.lang +0 -36
  59. data/app/assets/javascripts/dataTables/locales/nl.lang +0 -30
  60. data/app/assets/javascripts/effective_datatables/flash.js.coffee +0 -31
  61. data/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +0 -217
  62. data/app/assets/javascripts/effective_datatables/overrides.js.coffee +0 -7
  63. data/app/assets/javascripts/effective_datatables/reorder.js.coffee +0 -43
  64. data/app/assets/stylesheets/effective_datatables/_filters.scss +0 -7
  65. data/app/views/effective/datatables/_reorder_column.html.haml +0 -5
  66. data/config/locales/en.yml +0 -12
  67. data/config/locales/es.yml +0 -12
  68. data/config/locales/nl.yml +0 -12
@@ -1,15 +1,8 @@
1
1
  # These are expected to be called by a developer. They are part of the datatables DSL.
2
2
  module EffectiveDatatablesHelper
3
- def render_datatable(datatable, input_js: {}, buttons: true, charts: true, entries: true, filters: true, inline: false, pagination: true, search: true, simple: false, sort: true)
4
- raise 'expected datatable to be present' unless datatable
5
- raise 'expected input_js to be a Hash' unless input_js.kind_of?(Hash)
6
-
7
- if simple
8
- buttons = charts = entries = filters = pagination = search = sort = false
9
- end
10
3
 
11
- datatable.attributes[:inline] = true if inline
12
- datatable.attributes[:sortable] = false unless sort
4
+ def render_datatable(datatable, input_js: {}, buttons: true, charts: true, filters: true, simple: false)
5
+ raise 'expected datatable to be present' unless datatable
13
6
 
14
7
  datatable.view ||= self
15
8
 
@@ -20,48 +13,29 @@ module EffectiveDatatablesHelper
20
13
  charts = charts && datatable._charts.present?
21
14
  filters = filters && (datatable._scopes.present? || datatable._filters.present?)
22
15
 
23
- html_class = ['effective-datatable', datatable.html_class, ('hide-sort' unless sort), ('hide-search' unless search), ('hide-buttons' unless buttons)].compact.join(' ')
24
-
25
- if datatable.reorder? && !buttons
26
- buttons = true; input_js[:buttons] = false
27
- end
28
-
29
- # Build the datatables DOM option
30
- input_js[:dom] ||= [
31
- ("<'row'<'col-sm-12 dataTables_buttons'B>>" if buttons),
32
- "<'row'<'col-sm-12'tr>>",
33
- ("<'row'" if entries || pagination),
34
- ("<'col-sm-6 dataTables_entries'il>" if entries),
35
- ("<'col-sm-6'p>" if pagination),
36
- (">" if entries || pagination)
37
- ].compact.join
16
+ datatable.attributes[:simple] = true if simple
17
+ input_js[:buttons] = false if simple || !buttons
38
18
 
39
19
  effective_datatable_params = {
40
20
  id: datatable.to_param,
41
- class: html_class,
21
+ class: ('effective-datatable ' + Array(datatable.table_html_class).join(' ')),
42
22
  data: {
43
- 'attributes' => EffectiveDatatables.encrypt(datatable.attributes),
44
- 'authenticity-token' => form_authenticity_token,
45
23
  'bulk-actions' => datatable_bulk_actions(datatable),
46
24
  'columns' => datatable_columns(datatable),
25
+ 'cookie' => datatable.cookie_key,
47
26
  'display-length' => datatable.display_length,
48
- 'display-order' => datatable_display_order(datatable),
27
+ 'display-order' => [datatable.order_index, datatable.order_direction].to_json().html_safe,
49
28
  'display-records' => datatable.to_json[:recordsFiltered],
50
29
  'display-start' => datatable.display_start,
51
- 'inline' => inline.to_s,
52
- 'language' => EffectiveDatatables.language(I18n.locale),
53
- 'options' => input_js.to_json,
54
- 'reset' => (datatable_reset(datatable) if search),
55
- 'reorder' => datatable_reorder(datatable),
56
- 'reorder-index' => (datatable.columns[:_reorder][:index] if datatable.reorder?).to_s,
57
- 'simple' => simple.to_s,
58
- 'spinner' => '', # effective_bootstrap
30
+ 'options' => (input_js || {}).to_json.html_safe,
31
+ 'reset' => datatable_reset(datatable),
32
+ 'simple' => datatable.simple?.to_s,
59
33
  'source' => effective_datatables.datatable_path(datatable, {format: 'json'}),
60
34
  'total-records' => datatable.to_json[:recordsTotal]
61
35
  }
62
36
  }
63
37
 
64
- if (charts || filters)
38
+ if (charts || filters) && !simple
65
39
  output = ''.html_safe
66
40
 
67
41
  if charts
@@ -84,28 +58,59 @@ module EffectiveDatatablesHelper
84
58
  end
85
59
  end
86
60
 
87
- def render_inline_datatable(datatable)
88
- render_datatable(datatable, inline: true)
61
+ def render_simple_datatable(datatable)
62
+ raise 'expected datatable to be present' unless datatable
63
+
64
+ datatable.view ||= self
65
+
66
+ unless EffectiveDatatables.authorized?(controller, :index, datatable.collection_class)
67
+ return content_tag(:p, "You are not authorized to view this datatable. (cannot :index, #{datatable.collection_class})")
68
+ end
69
+
70
+ effective_datatable_params = {
71
+ id: datatable.to_param,
72
+ class: ('effective-datatable simple ' + Array(datatable.table_html_class).join(' ')),
73
+ data: {}
74
+ }
75
+
76
+ render(partial: 'effective/datatables/datatable',
77
+ locals: { datatable: datatable, effective_datatable_params: effective_datatable_params }
78
+ )
89
79
  end
90
80
 
91
- def render_simple_datatable(datatable)
92
- render_datatable(datatable, simple: true)
81
+ def render_datatable_filters(datatable)
82
+ raise 'expected datatable to be present' unless datatable
83
+
84
+ datatable.view ||= self
85
+ return unless datatable._scopes.present? || datatable._filters.present?
86
+
87
+ if datatable._filters_form_required?
88
+ render partial: 'effective/datatables/filters', locals: { datatable: datatable }
89
+ else
90
+ render(partial: 'effective/datatables/filters', locals: { datatable: datatable }).gsub('<form', '<div').gsub('/form>', '/div>').html_safe
91
+ end
92
+
93
93
  end
94
94
 
95
- def inline_datatable?
96
- params[:_datatable_id].present? && params[:_datatable_attributes].present?
95
+ def render_datatable_charts(datatable)
96
+ raise 'expected datatable to be present' unless datatable
97
+
98
+ datatable.view ||= self
99
+ return unless datatable._charts.present?
100
+
101
+ datatable._charts.map { |name, _| render_datatable_chart(datatable, name) }.join.html_safe
97
102
  end
98
103
 
99
- def inline_datatable
100
- return nil unless inline_datatable?
101
- return @_inline_datatable if @_inline_datatable
104
+ def render_datatable_chart(datatable, name)
105
+ raise 'expected datatable to be present' unless datatable
102
106
 
103
- datatable = EffectiveDatatables.find(params[:_datatable_id], params[:_datatable_attributes])
104
- datatable.view = self
107
+ datatable.view ||= self
108
+ return unless datatable._charts[name].present?
105
109
 
106
- EffectiveDatatables.authorize!(self, :index, datatable.collection_class)
110
+ chart = datatable._charts[name]
111
+ chart_data = datatable.to_json[:charts][name][:data]
107
112
 
108
- @_inline_datatable ||= datatable
113
+ render partial: chart[:partial], locals: { datatable: datatable, chart: chart, chart_data: chart_data }
109
114
  end
110
115
 
111
116
  end
@@ -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] && sortable),
17
- title: datatable_label_tag(datatable, name, opts),
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, t('effective_datatables.reset')), '#', class: 'btn btn-link btn-sm buttons-reset-search')
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 || simple_form_for(:datatable_search, url: '#', html: {id: "#{datatable.to_param}-form"}) { |f| @_effective_datatables_form_builder = f }
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
- input_html = {
40
+ options = opts[:search].except(:fuzzy).merge!(
95
41
  name: nil,
42
+ feedback: false,
43
+ label: false,
96
44
  value: value,
97
- title: title,
98
- pattern: pattern,
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 opts[:search][:as]
48
+ case options.delete(:as)
103
49
  when :string, :text, :number
104
- form.input name, label: false, required: false, value: value,
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.input name, label: false, required: false, value: value,
120
- as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_date_picker) ? :effective_date_picker : :string),
121
- placeholder: placeholder,
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.input name, label: false, required: false, value: value,
130
- as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_time_picker) ? :effective_time_picker : :string),
131
- placeholder: placeholder,
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
- form.input name, label: false, required: false, value: value,
139
- as: (ActionView::Helpers::FormBuilder.instance_methods.include?(:effective_select) ? :effective_select : :select),
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
- input_html[:data]['role'] = 'bulk-actions'
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
- as = opts[:as].to_s.chomp('_field').to_sym
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
- attributes = {
74
+ options = opts.except(:parse).merge(
75
+ placeholder: placeholder,
76
+ feedback: false,
77
+ label: false,
180
78
  value: value,
181
- selected: value,
182
- as: as,
183
- collection: collection,
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
- form.input :scope, label: false, required: false, checked: value,
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
- datatable.view ||= self
224
- return unless datatable._charts[name].present?
225
-
226
- chart = datatable._charts[name]
227
- chart_data = datatable.to_json[:charts][name][:data]
228
-
229
- render partial: chart[:partial], locals: { datatable: datatable, chart: chart, chart_data: chart_data }
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 :effective_resource
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 = nil)
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
- assert_attributes!
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 know about attributes but not about columns.
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
- # Check everything is okay
87
- validate_datatable!
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
- # Inline crud
127
- def inline?
128
- attributes[:inline] == true
129
- end
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 html_class
146
- Array(attributes[:class] || EffectiveDatatables.html_class).join(' ').presence
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}-#{[self.class, attributes].hash.abs.to_s.last(12)}"
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