effective_datatables 4.9.4 → 4.10.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -0
- data/app/assets/javascripts/effective_datatables/download.js.coffee +10 -0
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +2 -8
- data/app/controllers/effective/datatables_controller.rb +32 -0
- data/app/helpers/effective_datatables_helper.rb +9 -5
- data/app/helpers/effective_datatables_private_helper.rb +2 -13
- data/app/models/effective/datatable.rb +13 -0
- data/app/models/effective/effective_datatable/compute.rb +4 -3
- data/app/models/effective/effective_datatable/csv.rb +55 -0
- data/app/models/effective/effective_datatable/dsl/datatable.rb +11 -2
- data/app/models/effective/effective_datatable/format.rb +28 -11
- data/app/views/effective/datatables/_buttons.html.haml +14 -0
- data/config/effective_datatables.rb +3 -0
- data/config/locales/en.yml +1 -0
- data/config/locales/es.yml +1 -0
- data/config/locales/nl.yml +1 -0
- data/config/routes.rb +1 -0
- data/lib/effective_datatables/version.rb +1 -1
- data/lib/effective_datatables.rb +1 -0
- metadata +5 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 173cdec1d403c8203a7f3d3701104a76d7fd8fb04843c4989180b351b5096264
|
4
|
+
data.tar.gz: 70da4dcc029e6f7ac2a2f0d7f896734c4036eea227dfd5ecb6354f1efa59f531
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 474ead17fcde2196a4bdf06cdfa02c9d23e1dc4345126d79bcdf4fa3aa9785a358cce6d54a062862f17ec33c618a908db703a1eaa94e847a87df42dfe738b816
|
7
|
+
data.tar.gz: 55570bbe0d91f0bcdb24d818368a3a4dce9be6ffc0d7a99327121d8204df62a56b6eecc61a1bbbb6bb89b1feff5e4ea6d293497bb571ffff640331f14076d8b2
|
data/README.md
CHANGED
@@ -46,6 +46,7 @@ Please check out [Effective Datatables 3.x](https://github.com/code-and-effect/e
|
|
46
46
|
* [order](#order)
|
47
47
|
* [reorder](#reorder)
|
48
48
|
* [aggregate](#aggregate)
|
49
|
+
* [download](#download)
|
49
50
|
* [filters](#filters)
|
50
51
|
* [scope](#scope)
|
51
52
|
* [filter](#filter)
|
@@ -681,6 +682,30 @@ end.aggregate { |values, column| distance_of_time_in_words(values.min, values.ma
|
|
681
682
|
|
682
683
|
In the above example, `values` is an Array containing all row's values for one column at a time.
|
683
684
|
|
685
|
+
## download
|
686
|
+
|
687
|
+
Add a Download button which streams a CSV file containing all rows and columns in the table's collection, ignoring any search, sort or filtering.
|
688
|
+
|
689
|
+
This is an opt-in feature.
|
690
|
+
|
691
|
+
To enable, please set `config.download = true` in your `config/initializers/effective_datatables.rb` file.
|
692
|
+
|
693
|
+
Once enabled, you can disable it on an individual table by:
|
694
|
+
|
695
|
+
```ruby
|
696
|
+
datatable do
|
697
|
+
download false
|
698
|
+
end
|
699
|
+
```
|
700
|
+
|
701
|
+
and you can exclude individual columns from being rendered on the CSV export
|
702
|
+
|
703
|
+
```ruby
|
704
|
+
col :first_name, csv: false
|
705
|
+
```
|
706
|
+
|
707
|
+
The column will still appear in the export, but the contents will be blank.
|
708
|
+
|
684
709
|
## filters
|
685
710
|
|
686
711
|
Creates a single form with fields for each `filter` and a single radio input field for all `scopes`.
|
@@ -0,0 +1,10 @@
|
|
1
|
+
$(document).on 'click', '.dataTables_wrapper a.buttons-download', (event) ->
|
2
|
+
$button = $(event.currentTarget)
|
3
|
+
$table = $('#' + $button.attr('aria-controls'))
|
4
|
+
|
5
|
+
url = $table.data('source').replace('.json', '/download.csv')
|
6
|
+
attributes = 'attributes=' + encodeURIComponent($table.data('attributes'))
|
7
|
+
|
8
|
+
$button.attr('href', url + '?' + attributes)
|
9
|
+
|
10
|
+
setTimeout (=> $button.attr('href', 'download.csv')), 0
|
@@ -112,14 +112,8 @@ initializeDataTables = (target) ->
|
|
112
112
|
$table = $(api.table().node())
|
113
113
|
$buttons = $table.closest('.dataTables_wrapper').children().first().find('.dt-buttons')
|
114
114
|
|
115
|
-
if $table.data('
|
116
|
-
$buttons.prepend($table.data('
|
117
|
-
|
118
|
-
if $table.data('reorder')
|
119
|
-
$buttons.prepend($table.data('reorder'))
|
120
|
-
|
121
|
-
if $table.data('bulk-actions')
|
122
|
-
$buttons.prepend($table.data('bulk-actions'))
|
115
|
+
if $table.data('buttons-html')
|
116
|
+
$buttons.prepend($table.data('buttons-html'))
|
123
117
|
|
124
118
|
drawAggregates = ($table, aggregates) ->
|
125
119
|
$tfoot = $table.find('tfoot').first()
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
1
3
|
module Effective
|
2
4
|
class DatatablesController < ApplicationController
|
3
5
|
skip_log_page_views quiet: true if defined?(EffectiveLogging)
|
@@ -20,6 +22,36 @@ module Effective
|
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
25
|
+
def download
|
26
|
+
@datatable = EffectiveDatatables.find(params[:id], params[:attributes])
|
27
|
+
@datatable.view = view_context
|
28
|
+
|
29
|
+
EffectiveDatatables.authorize!(self, :index, @datatable.collection_class)
|
30
|
+
|
31
|
+
respond_to do |format|
|
32
|
+
format.csv do
|
33
|
+
headers.delete('Content-Length')
|
34
|
+
|
35
|
+
headers['X-Accel-Buffering'] = 'no'
|
36
|
+
headers['Cache-Control'] = 'no-cache'
|
37
|
+
headers["Content-Type"] = @datatable.csv_content_type
|
38
|
+
headers["Content-Disposition"] = %(attachment; filename="#{@datatable.csv_filename}")
|
39
|
+
headers['Last-Modified'] = Time.zone.now.ctime.to_s
|
40
|
+
|
41
|
+
self.response_body = @datatable.csv_stream
|
42
|
+
response.status = 200
|
43
|
+
end
|
44
|
+
|
45
|
+
# format.csv do
|
46
|
+
# send_data(@datatable.csv_file, filename: @datatable.csv_filename, type: @datatable.csv_content_type, disposition: 'attachment')
|
47
|
+
# end
|
48
|
+
|
49
|
+
format.all do
|
50
|
+
render(status: :unauthorized, body: 'Access Denied')
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
23
55
|
def reorder
|
24
56
|
begin
|
25
57
|
@datatable = EffectiveDatatables.find(params[:id], params[:attributes])
|
@@ -1,15 +1,21 @@
|
|
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, namespace: nil, pagination: true, search: true, simple: false, sort: true)
|
3
|
+
def render_datatable(datatable, input_js: {}, buttons: true, charts: true, download: nil, entries: true, filters: true, inline: false, namespace: nil, pagination: true, search: true, simple: false, sort: true)
|
4
4
|
raise 'expected datatable to be present' unless datatable
|
5
5
|
raise 'expected input_js to be a Hash' unless input_js.kind_of?(Hash)
|
6
6
|
|
7
|
+
if download.nil?
|
8
|
+
download = (buttons && EffectiveDatatables.download)
|
9
|
+
end
|
10
|
+
|
7
11
|
if simple
|
8
|
-
buttons = charts = entries = filters = pagination = search = sort = false
|
12
|
+
buttons = charts = download = entries = filters = pagination = search = sort = false
|
9
13
|
end
|
10
14
|
|
11
15
|
datatable.attributes[:inline] = true if inline
|
12
16
|
datatable.attributes[:sortable] = false unless sort
|
17
|
+
datatable.attributes[:searchable] = false unless search
|
18
|
+
datatable.attributes[:downloadable] = false unless download
|
13
19
|
datatable.attributes[:namespace] = namespace if namespace
|
14
20
|
|
15
21
|
datatable.view ||= self
|
@@ -44,7 +50,7 @@ module EffectiveDatatablesHelper
|
|
44
50
|
'all-label' => I18n.t('effective_datatables.all'),
|
45
51
|
'attributes' => EffectiveDatatables.encrypt(datatable.attributes),
|
46
52
|
'authenticity-token' => form_authenticity_token,
|
47
|
-
'
|
53
|
+
'buttons-html' => datatable_buttons(datatable),
|
48
54
|
'columns' => datatable_columns(datatable),
|
49
55
|
'default-visibility' => datatable.default_visibility.to_json,
|
50
56
|
'display-length' => datatable.display_length,
|
@@ -54,8 +60,6 @@ module EffectiveDatatablesHelper
|
|
54
60
|
'inline' => inline.to_s,
|
55
61
|
'language' => EffectiveDatatables.language(I18n.locale),
|
56
62
|
'options' => input_js.to_json,
|
57
|
-
'reset' => (datatable_reset(datatable) if search),
|
58
|
-
'reorder' => datatable_reorder(datatable),
|
59
63
|
'reorder-index' => (datatable.columns[:_reorder][:index] if datatable.reorder?).to_s,
|
60
64
|
'simple' => simple.to_s,
|
61
65
|
'spinner' => icon('spinner'), # effective_bootstrap
|
@@ -19,23 +19,12 @@ module EffectiveDatatablesPrivateHelper
|
|
19
19
|
end.to_json.html_safe
|
20
20
|
end
|
21
21
|
|
22
|
-
def datatable_bulk_actions(datatable)
|
23
|
-
if datatable._bulk_actions.present?
|
24
|
-
render(partial: '/effective/datatables/bulk_actions_dropdown', locals: { datatable: datatable }).gsub("'", '"').html_safe
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
22
|
def datatable_display_order(datatable)
|
29
23
|
((datatable.sortable? && datatable.order_index) ? [datatable.order_index, datatable.order_direction] : false).to_json.html_safe
|
30
24
|
end
|
31
25
|
|
32
|
-
def
|
33
|
-
|
34
|
-
end
|
35
|
-
|
36
|
-
def datatable_reorder(datatable)
|
37
|
-
return unless datatable.reorder? && EffectiveDatatables.authorized?(self, :update, datatable.collection_class)
|
38
|
-
link_to(content_tag(:span, t('effective_datatables.reorder')), '#', class: 'btn btn-link btn-sm buttons-reorder', disabled: true)
|
26
|
+
def datatable_buttons(datatable, search: true)
|
27
|
+
render('/effective/datatables/buttons', datatable: datatable, search: search).gsub("'", '"').html_safe
|
39
28
|
end
|
40
29
|
|
41
30
|
def datatable_new_resource_button(datatable, name, column)
|
@@ -30,6 +30,7 @@ module Effective
|
|
30
30
|
include Effective::EffectiveDatatable::Collection
|
31
31
|
include Effective::EffectiveDatatable::Compute
|
32
32
|
include Effective::EffectiveDatatable::Cookie
|
33
|
+
include Effective::EffectiveDatatable::Csv
|
33
34
|
include Effective::EffectiveDatatable::Format
|
34
35
|
include Effective::EffectiveDatatable::Hooks
|
35
36
|
include Effective::EffectiveDatatable::Params
|
@@ -140,6 +141,10 @@ module Effective
|
|
140
141
|
to_json[:recordsTotal] == 0
|
141
142
|
end
|
142
143
|
|
144
|
+
def to_csv
|
145
|
+
csv_file()
|
146
|
+
end
|
147
|
+
|
143
148
|
def to_json
|
144
149
|
@json ||= (
|
145
150
|
{
|
@@ -167,6 +172,14 @@ module Effective
|
|
167
172
|
!reorder? && attributes[:sortable] != false
|
168
173
|
end
|
169
174
|
|
175
|
+
def searchable?
|
176
|
+
attributes[:searchable] != false
|
177
|
+
end
|
178
|
+
|
179
|
+
def downloadable?
|
180
|
+
attributes[:downloadable] != false
|
181
|
+
end
|
182
|
+
|
170
183
|
# Whether the filters must be rendered as a <form> or we can keep the normal <div> behaviour
|
171
184
|
def _filters_form_required?
|
172
185
|
_form[:verb].present?
|
@@ -58,13 +58,14 @@ module Effective
|
|
58
58
|
finalize(col)
|
59
59
|
end
|
60
60
|
|
61
|
-
def arrayize(collection)
|
61
|
+
def arrayize(collection, csv: false)
|
62
62
|
collection.map do |obj|
|
63
63
|
columns.map do |name, opts|
|
64
|
-
if state[:visible][name] == false && (name != order_name) # Sort by invisible array column
|
64
|
+
if state[:visible][name] == false && !csv && (name != order_name) # Sort by invisible array column
|
65
|
+
BLANK
|
66
|
+
elsif csv && !opts[:csv]
|
65
67
|
BLANK
|
66
68
|
elsif opts[:compute]
|
67
|
-
|
68
69
|
if array_collection?
|
69
70
|
dsl_tool.instance_exec(obj, obj[opts[:index]], &opts[:compute])
|
70
71
|
else
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'csv'
|
2
|
+
|
3
|
+
module Effective
|
4
|
+
module EffectiveDatatable
|
5
|
+
module Csv
|
6
|
+
|
7
|
+
def csv_filename
|
8
|
+
self.class.name.underscore.parameterize + '.csv'
|
9
|
+
end
|
10
|
+
|
11
|
+
def csv_content_type
|
12
|
+
'text/csv; charset=utf-8'
|
13
|
+
end
|
14
|
+
|
15
|
+
def csv_header
|
16
|
+
columns.map { |_, opts| opts[:label] || '' }
|
17
|
+
end
|
18
|
+
|
19
|
+
def csv_file
|
20
|
+
CSV.generate do |csv|
|
21
|
+
csv << csv_header()
|
22
|
+
|
23
|
+
collection.send(csv_collection_method) do |resources|
|
24
|
+
resources = arrayize(resources, csv: true)
|
25
|
+
format(resources, csv: true)
|
26
|
+
finalize(resources)
|
27
|
+
|
28
|
+
resources.each { |resource| csv << resource }
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def csv_stream
|
34
|
+
EffectiveResources.with_resource_enumerator do |lines|
|
35
|
+
lines << CSV.generate_line(csv_header)
|
36
|
+
|
37
|
+
collection.public_send(csv_collection_method) do |resources|
|
38
|
+
resources = arrayize(resources, csv: true)
|
39
|
+
format(resources, csv: true)
|
40
|
+
finalize(resources)
|
41
|
+
|
42
|
+
resources.each { |resource| lines << CSV.generate_line(resource) }
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
def csv_collection_method
|
50
|
+
(active_record_collection? ? :find_in_batches : :to_a)
|
51
|
+
end
|
52
|
+
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -24,11 +24,15 @@ module Effective
|
|
24
24
|
reorder_col(name)
|
25
25
|
end
|
26
26
|
|
27
|
+
def download(bool)
|
28
|
+
datatable.attributes[:downloadable] = bool
|
29
|
+
end
|
30
|
+
|
27
31
|
# A col has its internal values sorted/searched before the block is run
|
28
32
|
# Anything done in the block, is purely a format on the after sorted/ordered value
|
29
33
|
# the original object == the computed value, which is yielded to the format block
|
30
34
|
# You can't do compute with .col
|
31
|
-
def col(name, action: nil, as: nil, col_class: nil, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: nil, th: nil, th_append: nil, visible: true, &format)
|
35
|
+
def col(name, action: nil, as: nil, col_class: nil, csv: true, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: nil, th: nil, th_append: nil, visible: true, &format)
|
32
36
|
raise 'You cannot use partial: ... with the block syntax' if partial && block_given?
|
33
37
|
|
34
38
|
name = name.to_sym unless name.to_s.include?('.')
|
@@ -38,6 +42,7 @@ module Effective
|
|
38
42
|
as: as,
|
39
43
|
compute: nil,
|
40
44
|
col_class: col_class,
|
45
|
+
csv: csv,
|
41
46
|
format: (format if block_given?),
|
42
47
|
index: nil,
|
43
48
|
label: (label.nil? ? name.to_s.split('.').last.titleize : label),
|
@@ -56,7 +61,7 @@ module Effective
|
|
56
61
|
|
57
62
|
# A val is a computed value that is then sorted/searched after the block is run
|
58
63
|
# You can have another block by calling .format afterwards to work on the computed value itself
|
59
|
-
def val(name, action: nil, as: nil, col_class: nil, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: false, th: nil, th_append: nil, visible: true, &compute)
|
64
|
+
def val(name, action: nil, as: nil, col_class: nil, csv: true, label: nil, partial: nil, partial_as: nil, responsive: 10000, search: {}, sort: true, sql_column: false, th: nil, th_append: nil, visible: true, &compute)
|
60
65
|
raise 'You cannot use partial: ... with the block syntax' if partial && block_given?
|
61
66
|
|
62
67
|
name = name.to_sym unless name.to_s.include?('.')
|
@@ -66,6 +71,7 @@ module Effective
|
|
66
71
|
as: as,
|
67
72
|
compute: (compute if block_given?),
|
68
73
|
col_class: col_class,
|
74
|
+
csv: csv,
|
69
75
|
format: nil,
|
70
76
|
index: nil,
|
71
77
|
label: (label.nil? ? name.to_s.split('.').last.titleize : label),
|
@@ -91,6 +97,7 @@ module Effective
|
|
91
97
|
compute: nil,
|
92
98
|
btn_class: (btn_class || 'btn-sm btn-outline-primary'),
|
93
99
|
col_class: col_class,
|
100
|
+
csv: false,
|
94
101
|
format: (format if block_given?),
|
95
102
|
index: nil,
|
96
103
|
inline: (inline.nil? ? datatable.inline? : inline),
|
@@ -130,6 +137,7 @@ module Effective
|
|
130
137
|
as: :bulk_actions,
|
131
138
|
compute: nil,
|
132
139
|
col_class: col_class,
|
140
|
+
csv: false,
|
133
141
|
format: nil,
|
134
142
|
index: nil,
|
135
143
|
input_name: (input_name || 'bulk_actions_resources'),
|
@@ -157,6 +165,7 @@ module Effective
|
|
157
165
|
as: :reorder,
|
158
166
|
compute: nil,
|
159
167
|
col_class: col_class,
|
168
|
+
csv: false,
|
160
169
|
format: nil,
|
161
170
|
index: nil,
|
162
171
|
label: false,
|
@@ -8,14 +8,16 @@ module Effective
|
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
|
-
def format(collection)
|
11
|
+
def format(collection, csv: false)
|
12
12
|
# We want to use the render :collection for each column that renders partials
|
13
13
|
rendered = {}
|
14
14
|
|
15
15
|
columns.each do |name, opts|
|
16
|
-
|
17
|
-
|
18
|
-
|
16
|
+
if state[:visible][name] == false && !csv
|
17
|
+
# Nothing to do
|
18
|
+
elsif csv && !opts[:csv]
|
19
|
+
# Nothing to do
|
20
|
+
elsif opts[:partial]
|
19
21
|
locals = { datatable: self, column: opts }.merge!(resource_col_locals(opts))
|
20
22
|
|
21
23
|
rendered[name] = (view.render(
|
@@ -26,6 +28,7 @@ module Effective
|
|
26
28
|
locals: locals,
|
27
29
|
spacer_template: SPACER_TEMPLATE
|
28
30
|
) || '').split(SPACER)
|
31
|
+
|
29
32
|
elsif opts[:as] == :actions # This is actions_col and actions_col do .. end, but not actions_col partial: 'something'
|
30
33
|
locals = { datatable: self, column: opts, spacer_template: SPACER_TEMPLATE }
|
31
34
|
|
@@ -45,7 +48,6 @@ module Effective
|
|
45
48
|
else
|
46
49
|
(view.render_resource_actions(collection.map { |row| row[opts[:index]] }, atts, &opts[:format]) || '').split(SPACER)
|
47
50
|
end
|
48
|
-
|
49
51
|
end
|
50
52
|
end
|
51
53
|
|
@@ -54,9 +56,11 @@ module Effective
|
|
54
56
|
index = opts[:index]
|
55
57
|
value = row[index]
|
56
58
|
|
57
|
-
|
58
|
-
if state[:visible][name] == false
|
59
|
+
formatted = (
|
60
|
+
if state[:visible][name] == false && !csv
|
59
61
|
NONVISIBLE
|
62
|
+
elsif csv && !opts[:csv]
|
63
|
+
BLANK
|
60
64
|
elsif opts[:as] == :actions
|
61
65
|
rendered[name][row_index]
|
62
66
|
elsif opts[:format] && rendered.key?(name)
|
@@ -66,14 +70,23 @@ module Effective
|
|
66
70
|
elsif opts[:partial]
|
67
71
|
rendered[name][row_index]
|
68
72
|
else
|
69
|
-
format_column(value, opts)
|
73
|
+
format_column(value, opts, csv: csv)
|
70
74
|
end
|
71
75
|
)
|
76
|
+
|
77
|
+
if csv && (opts[:format] || opts[:partial])
|
78
|
+
formatted = view.strip_tags(formatted)
|
79
|
+
|
80
|
+
formatted.gsub!("\n\n", ' ') unless formatted.frozen?
|
81
|
+
formatted.gsub!("\n", '') unless formatted.frozen?
|
82
|
+
end
|
83
|
+
|
84
|
+
row[index] = formatted
|
72
85
|
end
|
73
86
|
end
|
74
87
|
end
|
75
88
|
|
76
|
-
def format_column(value, column)
|
89
|
+
def format_column(value, column, csv: false)
|
77
90
|
return if value.nil? || (column[:resource] && value.blank?)
|
78
91
|
|
79
92
|
unless column[:as] == :email
|
@@ -90,7 +103,11 @@ module Effective
|
|
90
103
|
when :date
|
91
104
|
value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_date) : BLANK
|
92
105
|
when :datetime
|
93
|
-
|
106
|
+
if csv
|
107
|
+
value
|
108
|
+
else
|
109
|
+
value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_datetime) : BLANK
|
110
|
+
end
|
94
111
|
when :decimal
|
95
112
|
value
|
96
113
|
when :duration
|
@@ -102,7 +119,7 @@ module Effective
|
|
102
119
|
when :effective_roles
|
103
120
|
value.join(', ')
|
104
121
|
when :email
|
105
|
-
view.mail_to(value)
|
122
|
+
csv ? value : view.mail_to(value)
|
106
123
|
when :integer
|
107
124
|
value
|
108
125
|
when :percent
|
@@ -0,0 +1,14 @@
|
|
1
|
+
- if datatable._bulk_actions.present?
|
2
|
+
= render('/effective/datatables/bulk_actions_dropdown', datatable: datatable)
|
3
|
+
|
4
|
+
- if datatable.searchable?
|
5
|
+
= link_to '#', class: 'btn btn-link btn-sm buttons-reset-search' do
|
6
|
+
%span= t('effective_datatables.reset')
|
7
|
+
|
8
|
+
- if datatable.reorder? && EffectiveDatatables.authorized?(self, :update, datatable.collection_class)
|
9
|
+
= link_to '#', class: 'btn btn-link btn-sm buttons-reorder' do
|
10
|
+
%span= t('effective_datatables.reorder')
|
11
|
+
|
12
|
+
- if datatable.downloadable?
|
13
|
+
= link_to 'download.csv', class: 'btn btn-link btn-sm buttons-download', 'aria-controls': datatable.to_param do
|
14
|
+
%span= t('effective_datatables.download')
|
data/config/locales/en.yml
CHANGED
data/config/locales/es.yml
CHANGED
data/config/locales/nl.yml
CHANGED
data/config/routes.rb
CHANGED
@@ -2,6 +2,7 @@ EffectiveDatatables::Engine.routes.draw do
|
|
2
2
|
scope :module => 'effective' do
|
3
3
|
match 'datatables/:id(.:format)', to: 'datatables#show', via: [:get, :post], as: :datatable
|
4
4
|
match 'datatables/:id/reorder(.:format)', to: 'datatables#reorder', via: [:post], as: :reorder_datatable
|
5
|
+
match 'datatables/:id/download(.:format)', to: 'datatables#download', via: :get, as: :download_datatable
|
5
6
|
end
|
6
7
|
end
|
7
8
|
|
data/lib/effective_datatables.rb
CHANGED
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.
|
4
|
+
version: 4.10.0
|
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: 2021-
|
11
|
+
date: 2021-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -111,6 +111,7 @@ files:
|
|
111
111
|
- app/assets/javascripts/effective_datatables.js
|
112
112
|
- app/assets/javascripts/effective_datatables/bulk_actions.js.coffee
|
113
113
|
- app/assets/javascripts/effective_datatables/charts.js.coffee
|
114
|
+
- app/assets/javascripts/effective_datatables/download.js.coffee
|
114
115
|
- app/assets/javascripts/effective_datatables/events.js.coffee
|
115
116
|
- app/assets/javascripts/effective_datatables/filters.js.coffee
|
116
117
|
- app/assets/javascripts/effective_datatables/flash.js.coffee
|
@@ -141,6 +142,7 @@ files:
|
|
141
142
|
- app/models/effective/effective_datatable/collection.rb
|
142
143
|
- app/models/effective/effective_datatable/compute.rb
|
143
144
|
- app/models/effective/effective_datatable/cookie.rb
|
145
|
+
- app/models/effective/effective_datatable/csv.rb
|
144
146
|
- app/models/effective/effective_datatable/dsl.rb
|
145
147
|
- app/models/effective/effective_datatable/dsl/bulk_actions.rb
|
146
148
|
- app/models/effective/effective_datatable/dsl/charts.rb
|
@@ -154,6 +156,7 @@ files:
|
|
154
156
|
- app/views/effective/datatables/_active_storage_column.html.haml
|
155
157
|
- app/views/effective/datatables/_bulk_actions_column.html.haml
|
156
158
|
- app/views/effective/datatables/_bulk_actions_dropdown.html.haml
|
159
|
+
- app/views/effective/datatables/_buttons.html.haml
|
157
160
|
- app/views/effective/datatables/_chart.html.haml
|
158
161
|
- app/views/effective/datatables/_datatable.html.haml
|
159
162
|
- app/views/effective/datatables/_filters.html.haml
|