effective_datatables 4.3.6 → 4.3.7

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
  SHA1:
3
- metadata.gz: 0cdb353b5057246c492c440966e1de63df4b70b7
4
- data.tar.gz: 98cacf4aadcf11b4e831b00afabff3177a3e8559
3
+ metadata.gz: 4642aa5881ff3eb183f287db8c42b61c5ec18a3d
4
+ data.tar.gz: ac20c253b356faf06abba201e3f705b81d64e5e4
5
5
  SHA512:
6
- metadata.gz: 3ae86ea4a56ef6818ba3d450edd70e0ee86206a36ce99adee3947ce5951fb63c1e353c11d80077cd1beb4b15b0900e8d97fb477a720bce9114fbbda443da84d7
7
- data.tar.gz: d948ae33fc177a660554876724ffd9ae94d5b418428c3b9cef2bbe22465661740e5c490b12a29670851b0757fcc54aed54fef9722b1cf7f899f8cddb5b8e0915
6
+ metadata.gz: 309b3348a5507dd365dd6349b472301c29ca39ffd1cf77e516d031ed7a4c0c7a52b6fffe3cece2e59525acd1e412956cb26f645d13994287a2c898f7416fd573
7
+ data.tar.gz: 4b79372f60d9a26baeae025a63a84f2318d600adacc73b48525a463f21a6cc7b44bb7f066fdf53b6da7c11e36ee4ea8899a9458fcc407b966465a454d474d585
data/README.md CHANGED
@@ -454,7 +454,7 @@ These settings are loosely based on the regular datatypes, with some custom effe
454
454
  - `:currency` expects the underlying datatype to be a Float.
455
455
  - `:duration` expects the underlying datatype to be an Integer representing the number of minutes. 120 == 2 hours
456
456
  - `:email` expects the underlying datatype to be a String
457
- - `:percentage` expects the underlying datatype to be an Integer or a Float. 75 == 0.75 == 75%
457
+ - `:percent` expects the underlying datatype to be an Integer * 1000. 50000 == 50%. 50125 == 50.125%.
458
458
  - `:price` expects the underlying datatype to be an Integer representing the number of cents. 5000 == $50.00
459
459
  - `:resource` can be used for an Array based collection which includes an ActiveRecord object
460
460
 
@@ -3,7 +3,6 @@ initializeDataTables = ->
3
3
  datatable = $(this)
4
4
  options = datatable.data('options') || {}
5
5
  buttons_export_columns = options['buttons_export_columns'] || ':not(.col-actions)'
6
- simple = ('' + datatable.data('simple') == 'true')
7
6
  reorder = datatable.data('reorder')
8
7
 
9
8
  if options['buttons'] == false
@@ -49,7 +48,6 @@ initializeDataTables = ->
49
48
  deferLoading: [datatable.data('display-records'), datatable.data('total-records')]
50
49
  deferRender: true
51
50
  displayStart: datatable.data('display-start')
52
- dom: "<'row'<'col-sm-12 dataTables_buttons'B>><'row'<'col-sm-12'tr>><'row'<'col-sm-6 dataTables_entries'il><'col-sm-6'p>>"
53
51
  iDisplayLength: datatable.data('display-length')
54
52
  language: { 'lengthMenu': '&nbsp;with _MENU_ per page'}
55
53
  lengthMenu: [[5, 10, 25, 50, 100, 250, 500, 9999999], ['5', '10', '25', '50', '100', '250', '500', 'All']]
@@ -161,10 +159,6 @@ initializeDataTables = ->
161
159
  table = $input.closest('table.dataTable')
162
160
  table.DataTable().column("#{$input.data('column-name')}:name").search($input.val()).draw()
163
161
 
164
- if simple
165
- init_options['dom'] = "<'row'<'col-sm-12'tr>>" # Just show the table
166
- datatable.addClass('simple')
167
-
168
162
  if reorder
169
163
  init_options['rowReorder'] = { selector: 'td.col-_reorder', snapX: true, dataSrc: datatable.data('reorder-index') }
170
164
 
@@ -36,7 +36,7 @@ $(document).on 'ajax:success', '.dataTables_wrapper .col-actions', (event) ->
36
36
  true
37
37
 
38
38
  # The inline form has been submitted successfully
39
- $(document).on '.dataTables_wrapper .col-inline-form effective-form:success', (event, flash) ->
39
+ $(document).on 'effective-form:success', '.dataTables_wrapper .col-inline-form', (event, flash) ->
40
40
  $action = $(event.target)
41
41
 
42
42
  $tr = $action.closest('tr')
@@ -120,7 +120,7 @@ afterAction = ($action) ->
120
120
  buildRow = (length, payload) ->
121
121
  "<td class='col-inline-form' colspan='#{length-1}'><div class='container'>#{payload}</div></td>" +
122
122
  "<td class='col-actions col-actions-inline-form'>" +
123
- "<a href='#' class='btn btn-outline-primary' title='Cancel' data-role='inline-form-cancel'>Cancel</a>" +
123
+ "<a href='#' class='btn btn-sm btn-outline-primary' title='Cancel' data-role='inline-form-cancel'>Cancel</a>" +
124
124
  "</td>"
125
125
 
126
126
  expand = ($table) ->
@@ -139,12 +139,17 @@ div.dataTables_wrapper div.dataTables_processing {
139
139
  }
140
140
 
141
141
  // Simple styles
142
- table.dataTable.simple > thead {
142
+ table.dataTable.hide-sort > thead {
143
143
  .sorting { background-image: none; cursor: default; }
144
144
  .sorting_asc { background-image: none; cursor: default; }
145
145
  .sorting_desc { background-image: none; cursor: default; }
146
+ }
146
147
 
148
+ table.dataTable.hide-search > thead {
147
149
  .form-group { display: none; }
150
+ }
151
+
152
+ table.dataTable.hide-buttons {
148
153
  .col-bulk_actions { display: none; }
149
154
  }
150
155
 
@@ -1,11 +1,15 @@
1
1
  # These are expected to be called by a developer. They are part of the datatables DSL.
2
2
  module EffectiveDatatablesHelper
3
3
 
4
- def render_datatable(datatable, input_js: {}, buttons: true, charts: true, filters: true, simple: false, inline: false)
4
+ def render_datatable(datatable, input_js: {}, buttons: true, charts: true, entries: true, filters: true, inline: false, pagination: true, search: true, simple: false, sort: true)
5
5
  raise 'expected datatable to be present' unless datatable
6
6
 
7
- datatable.attributes[:simple] = true if simple
7
+ if simple
8
+ buttons = charts = entries = filters = pagination = search = sort = false
9
+ end
10
+
8
11
  datatable.attributes[:inline] = true if inline
12
+ datatable.attributes[:sortable] = false unless sort
9
13
 
10
14
  datatable.view ||= self
11
15
 
@@ -16,11 +20,25 @@ module EffectiveDatatablesHelper
16
20
  charts = charts && datatable._charts.present?
17
21
  filters = filters && (datatable._scopes.present? || datatable._filters.present?)
18
22
 
19
- input_js[:buttons] = false if simple || !buttons
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
20
38
 
21
39
  effective_datatable_params = {
22
40
  id: datatable.to_param,
23
- class: ('effective-datatable ' + Array(datatable.table_html_class).join(' ')),
41
+ class: html_class,
24
42
  data: {
25
43
  'bulk-actions' => datatable_bulk_actions(datatable),
26
44
  'columns' => datatable_columns(datatable),
@@ -29,19 +47,19 @@ module EffectiveDatatablesHelper
29
47
  'display-order' => datatable_display_order(datatable),
30
48
  'display-records' => datatable.to_json[:recordsFiltered],
31
49
  'display-start' => datatable.display_start,
32
- 'inline' => datatable.inline?.to_s,
50
+ 'inline' => inline.to_s,
33
51
  'options' => (input_js || {}).to_json.html_safe,
34
- 'reset' => datatable_reset(datatable),
52
+ 'reset' => (datatable_reset(datatable) if search),
35
53
  'reorder' => datatable_reorder(datatable),
36
54
  'reorder-index' => (datatable.columns[:_reorder][:index] if datatable.reorder?).to_s,
37
- 'simple' => datatable.simple?.to_s,
55
+ 'simple' => simple.to_s,
38
56
  'spinner' => icon('spinner'), # effective_bootstrap
39
57
  'source' => effective_datatables.datatable_path(datatable, {format: 'json'}),
40
58
  'total-records' => datatable.to_json[:recordsTotal]
41
59
  }
42
60
  }
43
61
 
44
- if (charts || filters) && !simple
62
+ if (charts || filters)
45
63
  output = ''.html_safe
46
64
 
47
65
  if charts
@@ -69,23 +87,7 @@ module EffectiveDatatablesHelper
69
87
  end
70
88
 
71
89
  def render_simple_datatable(datatable)
72
- raise 'expected datatable to be present' unless datatable
73
-
74
- datatable.view ||= self
75
-
76
- unless EffectiveDatatables.authorized?(controller, :index, datatable.collection_class)
77
- return content_tag(:p, "You are not authorized to view this datatable. (cannot :index, #{datatable.collection_class})")
78
- end
79
-
80
- effective_datatable_params = {
81
- id: datatable.to_param,
82
- class: ('effective-datatable simple ' + Array(datatable.table_html_class).join(' ')),
83
- data: {}
84
- }
85
-
86
- render(partial: 'effective/datatables/datatable',
87
- locals: { datatable: datatable, effective_datatable_params: effective_datatable_params }
88
- )
90
+ render_datatable(datatable, simple: true)
89
91
  end
90
92
 
91
93
  def inline_datatable?
@@ -40,7 +40,7 @@ module EffectiveDatatablesPrivateHelper
40
40
 
41
41
  def datatable_new_resource_button(datatable, name, column)
42
42
  if column[:inline] && column[:actions][:new] != false
43
- actions = {'New' => { action: :new, class: 'btn btn-outline-primary', 'data-remote': true } }
43
+ actions = {'New' => { action: :new, class: ['btn', column[:btn_class].presence].compact.join(' '), 'data-remote': true } }
44
44
  render_resource_actions(datatable.resource.klass, actions: actions, effective_resource: datatable.resource) # Will only work if permitted
45
45
  end
46
46
  end
@@ -122,24 +122,18 @@ module Effective
122
122
  )
123
123
  end
124
124
 
125
- # When simple only a table will be rendered with
126
- # no sorting, no filtering, no export buttons, no pagination, no per page, no colReorder
127
- # default sorting only, default visibility only, all records returned, and responsive enabled
128
- def simple?
129
- attributes[:simple] == true
130
- end
131
-
132
125
  # Inline crud
133
126
  def inline?
134
127
  attributes[:inline] == true
135
128
  end
136
129
 
130
+ # Reordering
137
131
  def reorder?
138
132
  columns.key?(:_reorder)
139
133
  end
140
134
 
141
135
  def sortable?
142
- !simple? && !reorder?
136
+ !reorder? && attributes[:sortable] != false
143
137
  end
144
138
 
145
139
  # Whether the filters must be rendered as a <form> or we can keep the normal <div> behaviour
@@ -147,8 +141,8 @@ module Effective
147
141
  _form[:verb].present?
148
142
  end
149
143
 
150
- def table_html_class
151
- attributes[:class] || EffectiveDatatables.html_class
144
+ def html_class
145
+ Array(attributes[:class] || EffectiveDatatables.html_class).join(' ').presence
152
146
  end
153
147
 
154
148
  def to_param
@@ -132,7 +132,7 @@ module Effective
132
132
 
133
133
  case aggregate[:name]
134
134
  when :total
135
- if [:percentage].include?(column[:as])
135
+ if [:percent].include?(column[:as])
136
136
  BLANK
137
137
  elsif values.all? { |value| value.kind_of?(Numeric) }
138
138
  values.sum
@@ -82,13 +82,14 @@ module Effective
82
82
  )
83
83
  end
84
84
 
85
- def actions_col(col_class: nil, inline: nil, partial: nil, partial_as: nil, actions_partial: nil, responsive: 5000, visible: true, **actions, &format)
85
+ def actions_col(btn_class: nil, col_class: nil, inline: nil, partial: nil, partial_as: nil, actions_partial: nil, responsive: 5000, visible: true, **actions, &format)
86
86
  raise 'You can only have one actions column' if datatable.columns[:_actions].present?
87
87
 
88
88
  datatable._columns[:_actions] = Effective::DatatableColumn.new(
89
89
  action: false,
90
90
  as: :actions,
91
91
  compute: nil,
92
+ btn_class: (btn_class || 'btn-sm btn-outline-primary'),
92
93
  col_class: col_class,
93
94
  format: (format if block_given?),
94
95
  index: nil,
@@ -29,7 +29,7 @@ module Effective
29
29
  elsif opts[:as] == :actions # This is actions_col and actions_col do .. end, but not actions_col partial: 'something'
30
30
  resources = collection.map { |row| row[opts[:index]] }
31
31
  locals = { datatable: self, column: opts, spacer_template: SPACER_TEMPLATE }
32
- atts = { actions: actions_col_actions(opts), effective_resource: resource, locals: locals, partial: opts[:actions_partial] }.merge(opts[:actions])
32
+ atts = { actions: actions_col_actions(opts), effective_resource: resource, locals: locals, partial: opts[:actions_partial], btn_class: opts[:btn_class] }.merge(opts[:actions])
33
33
 
34
34
  rendered[name] = (view.render_resource_actions(resources, atts, &opts[:format]) || '').split(SPACER)
35
35
  end
@@ -97,10 +97,10 @@ module Effective
97
97
  view.mail_to(value)
98
98
  when :integer
99
99
  value
100
- when :percentage
100
+ when :percent
101
101
  case value
102
- when Integer ; "#{value}%"
103
- when Numeric ; view.number_to_percentage(value * 100, precision: 2)
102
+ when Integer ; view.number_to_percentage(value / 1000.0, precision: 3).gsub('.000%', '%')
103
+ when Numeric ; view.number_to_percentage(value, precision: 3).gsub('.000%', '%')
104
104
  end
105
105
  when :price
106
106
  case value
@@ -127,22 +127,20 @@ module Effective
127
127
  def resource_col_locals(opts)
128
128
  return {} unless (resource = opts[:resource]).present?
129
129
 
130
+ polymorphic = (opts[:as] == :belongs_to_polymorphic)
131
+
130
132
  locals = { name: opts[:name], effective_resource: resource, show_action: false, edit_action: false }
131
133
 
132
134
  case opts[:action]
133
135
  when :edit
134
- locals[:edit_action] = (resource.routes[:edit] && EffectiveDatatables.authorized?(view.controller, :edit, resource.klass))
136
+ locals[:edit_action] = (resource.routes[:edit].present? || polymorphic)
135
137
  when :show
136
- locals[:show_action] = (resource.routes[:show] && EffectiveDatatables.authorized?(view.controller, :show, resource.klass))
138
+ locals[:show_action] = (resource.routes[:show].present? || polymorphic)
137
139
  when false
138
- # Nothing
140
+ # Nothing. Already false.
139
141
  else
140
- # Fallback to defaults - check edit then show
141
- if resource.routes[:edit] && EffectiveDatatables.authorized?(view.controller, :edit, resource.klass)
142
- locals[:edit_action] = true
143
- elsif resource.routes[:show] && EffectiveDatatables.authorized?(view.controller, :show, resource.klass)
144
- locals[:show_action] = true
145
- end
142
+ locals[:edit_action] = (resource.routes[:edit].present? || polymorphic)
143
+ locals[:show_action] = (resource.routes[:show].present? || polymorphic)
146
144
  end
147
145
 
148
146
  locals
@@ -140,7 +140,7 @@ module Effective
140
140
 
141
141
  search[:value] ||= search.delete(:selected) if search.key?(:selected)
142
142
 
143
- search[:as] ||= :select if (search.key?(:collection) && opts[:as] != :belongs_to_polymorphic)
143
+ search[:as] ||= :select if search.key?(:collection)
144
144
 
145
145
  search[:fuzzy] = true unless search.key?(:fuzzy)
146
146
 
@@ -149,6 +149,11 @@ module Effective
149
149
  elsif search[:as] != :string
150
150
  search.reverse_merge!(resource.search_form_field(name, opts[:as]))
151
151
  end
152
+
153
+ # Assign default include_null
154
+ if search[:as] == :select && !search.key?(:include_null)
155
+ search[:include_null] = true
156
+ end
152
157
  end
153
158
  end
154
159
 
@@ -160,10 +165,19 @@ module Effective
160
165
  next unless attribute.ends_with?('_id')
161
166
 
162
167
  associated = attribute.gsub(/_id\z/, '').to_sym # Replace last _id
163
- next unless columns[associated] && columns[associated][:as] == :belongs_to
164
168
 
165
- @_collection = @_collection.where(attribute => value)
166
- columns.delete(associated)
169
+ next unless columns[associated]
170
+
171
+ if columns[associated][:as] == :belongs_to
172
+ @_collection = @_collection.where(attribute => value)
173
+ columns.delete(associated)
174
+ elsif columns[associated][:as] == :belongs_to_polymorphic
175
+ associated_type = attributes["#{associated}_type".to_sym] || raise("Expected #{associated}_type attribute to be present when #{associated}_id is present on a polymorphic belongs to")
176
+
177
+ @_collection = @_collection.where(attribute => value).where("#{associated}_type" => associated_type)
178
+ columns.delete(associated)
179
+ end
180
+
167
181
  end.present?
168
182
 
169
183
  load_columns! if changed
@@ -1,8 +1,8 @@
1
1
  - Array(datatable.array_collection? ? resource : resource.send(name)).each do |resource|
2
2
  .col-resource_item
3
- - if show_action
4
- = link_to resource.to_s, effective_resource.action_path(:show, resource), title: resource.to_s
5
- - elsif edit_action
3
+ - if edit_action && EffectiveDatatables.authorized?(controller, :edit, resource)
6
4
  = link_to resource.to_s, effective_resource.action_path(:edit, resource), title: resource.to_s
5
+ - elsif show_action && EffectiveDatatables.authorized?(controller, :show, resource)
6
+ = link_to resource.to_s, effective_resource.action_path(:show, resource), title: resource.to_s
7
7
  - else
8
8
  = resource.to_s.html_safe
@@ -1,3 +1,3 @@
1
1
  module EffectiveDatatables
2
- VERSION = '4.3.6'.freeze
2
+ VERSION = '4.3.7'.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.3.6
4
+ version: 4.3.7
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: 2018-10-29 00:00:00.000000000 Z
11
+ date: 2018-10-31 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails