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 +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
         
     |