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 +4 -4
- data/README.md +1 -1
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +0 -6
- data/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +2 -2
- data/app/assets/stylesheets/effective_datatables/_overrides.scss +6 -1
- data/app/helpers/effective_datatables_helper.rb +27 -25
- data/app/helpers/effective_datatables_private_helper.rb +1 -1
- data/app/models/effective/datatable.rb +4 -10
- data/app/models/effective/effective_datatable/compute.rb +1 -1
- data/app/models/effective/effective_datatable/dsl/datatable.rb +2 -1
- data/app/models/effective/effective_datatable/format.rb +11 -13
- data/app/models/effective/effective_datatable/resource.rb +18 -4
- data/app/views/effective/datatables/_resource_column.html.haml +3 -3
- data/lib/effective_datatables/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4642aa5881ff3eb183f287db8c42b61c5ec18a3d
|
4
|
+
data.tar.gz: ac20c253b356faf06abba201e3f705b81d64e5e4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
- `:
|
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': ' 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
|
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.
|
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,
|
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
|
-
|
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
|
-
|
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:
|
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' =>
|
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' =>
|
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)
|
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
|
-
|
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
|
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
|
-
!
|
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
|
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
|
@@ -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 :
|
100
|
+
when :percent
|
101
101
|
case value
|
102
|
-
when Integer ;
|
103
|
-
when Numeric ; view.number_to_percentage(value
|
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]
|
136
|
+
locals[:edit_action] = (resource.routes[:edit].present? || polymorphic)
|
135
137
|
when :show
|
136
|
-
locals[:show_action] = (resource.routes[:show]
|
138
|
+
locals[:show_action] = (resource.routes[:show].present? || polymorphic)
|
137
139
|
when false
|
138
|
-
# Nothing
|
140
|
+
# Nothing. Already false.
|
139
141
|
else
|
140
|
-
|
141
|
-
|
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
|
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
|
-
|
166
|
-
|
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
|
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
|
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.
|
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-
|
11
|
+
date: 2018-10-31 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|