effective_datatables 3.7.7 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
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