effective_datatables 4.9.4 → 4.10.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 768310a5434c778a3e11512125d661bc4ce443a277bb7e15581e50224b81c48f
4
- data.tar.gz: 6b05137c54ef11ce9801b2e1fc48ee525641d2dd5507b7259e80c3387335404b
3
+ metadata.gz: 173cdec1d403c8203a7f3d3701104a76d7fd8fb04843c4989180b351b5096264
4
+ data.tar.gz: 70da4dcc029e6f7ac2a2f0d7f896734c4036eea227dfd5ecb6354f1efa59f531
5
5
  SHA512:
6
- metadata.gz: edf03e2147e95afd515bc357ac5436dca96c0d3f1aa4fd36ac040bc1cc0885a1a34a0d6ff69897b61bafe8542b46447bc59adc96d42167fd4efc6b98cd65006b
7
- data.tar.gz: 7027f034cee83b584d50290a34674295b3aca4d7b6cb0121ebd1dd052833ffdfaa0be50e26d493d736c8d8e7730aa89dc666b42c0e1219ba33c6ec495f9c01da
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('reset')
116
- $buttons.prepend($table.data('reset'))
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
- 'bulk-actions' => datatable_bulk_actions(datatable),
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 datatable_reset(datatable)
33
- link_to(content_tag(:span, t('effective_datatables.reset')), '#', class: 'btn btn-link btn-sm buttons-reset-search')
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
- next unless state[:visible][name]
17
-
18
- if opts[:partial]
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
- row[index] = (
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
- value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_datetime) : BLANK
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')
@@ -43,4 +43,7 @@ EffectiveDatatables.setup do |config|
43
43
  config.format_datetime = '%F %H:%M'
44
44
  config.format_date = '%F'
45
45
  config.format_time = '%H:%M'
46
+
47
+ # Enable the Download button which serves a CSV of your collection
48
+ config.download = false
46
49
  end
@@ -2,6 +2,7 @@
2
2
  en:
3
3
  effective_datatables:
4
4
  apply: Apply
5
+ download: Download
5
6
  reset: Reset
6
7
  reorder: Reorder
7
8
  new: New
@@ -2,6 +2,7 @@
2
2
  es:
3
3
  effective_datatables:
4
4
  apply: Filtrar
5
+ download: Download
5
6
  reset: Reiniciar
6
7
  reorder: Reordenar
7
8
  new: Nuevo
@@ -2,6 +2,7 @@
2
2
  nl:
3
3
  effective_datatables:
4
4
  apply: Toepassen
5
+ download: Download
5
6
  reset: Reset
6
7
  reorder: Opnieuw ordenen
7
8
  new: Nieuwe
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
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveDatatables
2
- VERSION = '4.9.4'.freeze
2
+ VERSION = '4.10.0'.freeze
3
3
  end
@@ -21,6 +21,7 @@ module EffectiveDatatables
21
21
  mattr_accessor :format_time
22
22
 
23
23
  mattr_accessor :debug
24
+ mattr_accessor :download
24
25
 
25
26
  alias_method :max_cookie_size, :cookie_max_size
26
27
  alias_method :max_cookie_size=, :cookie_max_size=
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.9.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-09-23 00:00:00.000000000 Z
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