effective_datatables 4.8.0 → 4.8.16

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.
Files changed (33) hide show
  1. checksums.yaml +4 -4
  2. data/MIT-LICENSE +1 -1
  3. data/README.md +199 -24
  4. data/app/assets/javascripts/effective_datatables/flash.js.coffee +1 -1
  5. data/app/assets/javascripts/effective_datatables/initialize.js.coffee +9 -4
  6. data/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +42 -13
  7. data/app/assets/javascripts/effective_datatables/reorder.js.coffee +8 -2
  8. data/app/assets/javascripts/vendor/jquery.delayedChange.js +1 -1
  9. data/app/assets/stylesheets/dataTables/dataTables.bootstrap4.scss +1 -3
  10. data/app/helpers/effective_datatables_helper.rb +3 -1
  11. data/app/helpers/effective_datatables_private_helper.rb +12 -8
  12. data/app/models/effective/datatable.rb +28 -2
  13. data/app/models/effective/datatable_value_tool.rb +0 -6
  14. data/app/models/effective/effective_datatable/attributes.rb +1 -0
  15. data/app/models/effective/effective_datatable/compute.rb +1 -0
  16. data/app/models/effective/effective_datatable/cookie.rb +2 -0
  17. data/app/models/effective/effective_datatable/dsl/filters.rb +1 -1
  18. data/app/models/effective/effective_datatable/format.rb +9 -9
  19. data/app/models/effective/effective_datatable/params.rb +5 -0
  20. data/app/models/effective/effective_datatable/resource.rb +10 -9
  21. data/app/models/effective/effective_datatable/state.rb +1 -1
  22. data/app/views/effective/datatables/_active_storage_column.html.haml +1 -1
  23. data/app/views/effective/datatables/_bulk_actions_dropdown.html.haml +3 -2
  24. data/config/effective_datatables.rb +5 -1
  25. data/config/locales/en.yml +3 -1
  26. data/config/locales/es.yml +3 -1
  27. data/config/locales/nl.yml +3 -1
  28. data/lib/effective_datatables/version.rb +1 -1
  29. data/lib/effective_datatables.rb +4 -0
  30. metadata +6 -9
  31. data/app/datatables/effective_style_guide_datatable.rb +0 -45
  32. data/app/models/effective/access_denied.rb +0 -17
  33. data/app/views/effective/style_guide/_effective_datatables.html.haml +0 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: c5a9a4233ee452020c92387b3bb140eac9df58bd52548c55a2eb41881c731f67
4
- data.tar.gz: f738131e50148095ea9c1cee3b0f68911d4b2a4f1815b7d5aa6445ec4d849a49
3
+ metadata.gz: cb1dc8f3ac21b885c37e56552192568b059350efcdcd7bd79784d87d91a4bee3
4
+ data.tar.gz: 46094ee0a00e9246b8dde73c2c9ab4f531c84a287f2cd7db7da467cc0dab6d92
5
5
  SHA512:
6
- metadata.gz: 2279b8c6b0f72dc5427a2d0cc876ee83021806a3152d325edcccbaf8532dd65de27c1a8275320a306568790a60965d6235ee585e4bba41c1337148568df62d51
7
- data.tar.gz: a7e514c7caf226a633fbd5d6098df1241b38336343fc9d6927f3bab07419d56300c06c4cecab752ed4a43819f9f6946c820cff5af7e0b25c317922a06625155e
6
+ metadata.gz: 51f91cf414121df572748ce03da5732b53011ad113db667b95284276f9ec628ec12ff0f8f614567ab88c770f9fa674059c6b8ca9a1ab1a5701e4dd8dbd509c2f
7
+ data.tar.gz: 1fbacd63b25ba9ba0556ccfec605a07ff5a3c6e5ddfc8da6dc723e66bfc4a72cb0d9c97d796a4acdb419e7fa5d1a2c8b8ec760bb4df77dbcee9b79708fce235d
data/MIT-LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright 2019 Code and Effect Inc.
1
+ Copyright 2021 Code and Effect Inc.
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/README.md CHANGED
@@ -8,7 +8,7 @@ Does the right thing with searching sql columns as well as computed values from
8
8
 
9
9
  Displays links to associated edit/show/destroy actions based on `current_user` authorized actions.
10
10
 
11
- Other features include aggregate (total/average) footer rows, bulk actions, show/hide columns, responsive collapsing columns and Google charts.
11
+ Other features include aggregate (total/average) footer rows, bulk actions, show/hide columns, responsive collapsing columns, google charts, and inline crud.
12
12
 
13
13
  This gem includes the jQuery DataTables assets.
14
14
 
@@ -54,7 +54,8 @@ Please check out [Effective Datatables 3.x](https://github.com/code-and-effect/e
54
54
  * [bulk_action](#bulk_action_divider)
55
55
  * [bulk_download](#bulk_download)
56
56
  * [bulk_action_content](#bulk_action_content)
57
- * [charts](#charts)
57
+ * [Charts](#charts)
58
+ * [Inline](#inline)
58
59
  * [Extras](#extras)
59
60
  * [Advanced Search and Sort](#advanced-search-and-sort)
60
61
  * [Addtional Functionality](#additional-functionality)
@@ -453,7 +454,7 @@ The `datatable do ... end` block configures a table of data.
453
454
 
454
455
  Initialize the datatable in your controller or view, `@datatable = PostsDatatable.new(self)`, and render it in your view `<%= render_datatable(@datatable) %>`
455
456
 
456
- ### col
457
+ ## col
457
458
 
458
459
  This is the main DSL method that you will interact with.
459
460
 
@@ -526,7 +527,7 @@ You can also use the joined syntax, `col 'user.email'` to create a column for ju
526
527
 
527
528
  This feature is only working with `belongs_to` and you need to add the `.joins(:user)` to the collection do ... end block yourself.
528
529
 
529
- ### val
530
+ ## val
530
531
 
531
532
  Shorthand for value, this command also creates a column on the datatable.
532
533
 
@@ -548,7 +549,7 @@ This is implemented as a full Array search/sort and is much slower for large dat
548
549
 
549
550
  The `.format do ... end` block can then be used to apply custom formatting.
550
551
 
551
- ### bulk_actions_col
552
+ ## bulk_actions_col
552
553
 
553
554
  Creates a column of checkboxes for use with the `bulk_actions` section.
554
555
 
@@ -558,7 +559,7 @@ Use these checkboxes to select all / none / one or more rows for the `bulk_actio
558
559
 
559
560
  You can only have one `bulk_actions_col` per datatable.
560
561
 
561
- ### actions_col
562
+ ## actions_col
562
563
 
563
564
  When working with an ActiveRecord based collection, this column will consider the `current_user`'s authorization, and generate links to edit, show and destroy actions for any collection class.
564
565
 
@@ -596,7 +597,7 @@ Any `data-remote` actions will be hijacked and performed as inline ajax by datat
596
597
 
597
598
  If you'd like to opt-out of this behavior, use `actions_col(inline: false)` or add `data-inline: false` to your action link.
598
599
 
599
- ### length
600
+ ## length
600
601
 
601
602
  Sets the default number of rows per page. Valid lengths are `5`, `10`, `25`, `50`, `100`, `250`, `500`, `:all`
602
603
 
@@ -606,7 +607,7 @@ When not specified, effective_datatables uses the default as per the `config/ini
606
607
  length 100
607
608
  ```
608
609
 
609
- ### order
610
+ ## order
610
611
 
611
612
  Sets the default order of table rows. The first argument is the column, the second the direction.
612
613
 
@@ -618,7 +619,7 @@ When not specified, effective_datatables will sort by the first defined column.
618
619
  order :created_at, :asc|:desc
619
620
  ```
620
621
 
621
- ### reorder
622
+ ## reorder
622
623
 
623
624
  Enables drag-and-drop row re-ordering.
624
625
 
@@ -636,7 +637,7 @@ reorder :position
636
637
 
637
638
  Using `reorder` will sort the collection by this field and disable all other column sorting.
638
639
 
639
- ### aggregate
640
+ ## aggregate
640
641
 
641
642
  The `aggregate` command inserts a row in the table's `tfoot`.
642
643
 
@@ -681,7 +682,7 @@ The form is submitted by an AJAX POST action, or, in some advanced circumstances
681
682
 
682
683
  Initialize the datatable in your controller or view, `@datatable = PostsDatatable.new(self)`, and render its filters anywhere with `<%= render_datatable_filters(@datatable) %>`.
683
684
 
684
- ### scope
685
+ ## scope
685
686
 
686
687
  All defined scopes are rendered as a single radio button form field. Works great with the [effective_form_inputs](https://github.com/code-and-effect/effective_form_inputs) gem.
687
688
 
@@ -705,7 +706,7 @@ class Post < ApplicationRecord | ActiveRecord::Base
705
706
  end
706
707
  ```
707
708
 
708
- ### filter
709
+ ## filter
709
710
 
710
711
  Each filter has a name and a default/fallback value. If the form is submitted blank, the default values are used.
711
712
 
@@ -758,7 +759,7 @@ Creates a single dropdown menu with a link to each action, download or content.
758
759
 
759
760
  Along with this section, you must put a `bulk_actions_col` somewhere in your `datatable do ... end` section.
760
761
 
761
- ### bulk_action
762
+ ## bulk_action
762
763
 
763
764
  Creates a link that becomes clickable when one or more checkbox/rows are selected as per the `bulk_actions_col` column.
764
765
 
@@ -814,11 +815,11 @@ def approve!
814
815
  end
815
816
  ```
816
817
 
817
- ### bulk_action_divider
818
+ ## bulk_action_divider
818
819
 
819
820
  Inserts a menu divider `<li class='divider' role='separator'></li>`
820
821
 
821
- ### bulk_download
822
+ ## bulk_download
822
823
 
823
824
  So it turns out there are some http issues with using an AJAX action to download a file.
824
825
 
@@ -859,7 +860,7 @@ def bulk_export_report
859
860
  end
860
861
  ```
861
862
 
862
- ### bulk_action_content
863
+ ## bulk_action_content
863
864
 
864
865
  Blindly inserts content into the dropdown.
865
866
 
@@ -873,7 +874,7 @@ end
873
874
 
874
875
  Don't actually use this.
875
876
 
876
- ## charts
877
+ # Charts
877
878
 
878
879
  Create a [Google Chart](https://developers.google.com/chart/interactive/docs/quick_start) based on your searched collection, filters and attributes.
879
880
 
@@ -930,11 +931,169 @@ All options passed to `chart` are used to initialize the chart javascript.
930
931
 
931
932
  By default, the only package that is loaded is `corechart`, see the `config/initializers/effective_datatables.rb` file to add more packages.
932
933
 
933
- ## Extras
934
+ # Inline
935
+
936
+ Any datatable can be used as an inline datatable, to create, update and destroy resources without leaving the current page.
937
+
938
+ If your datatable is already working with `actions_col` and being rendered from an `Effective::CrudController` controller, all you need to do is change your view from `render_datatable(@datatable)` to `render_datatable(@datatable, inline: true)`.
939
+
940
+ Click here for a [Inline Live Demo](https://effective-datatables-demo.herokuapp.com/things) and here for an [Inline Code Example](https://github.com/code-and-effect/effective_datatables_demo)
941
+ (only the `thing` data model and `things_datatable` are being used inline)
942
+
943
+ To use effective_datatables as an inline CRUD builder, you will be relying heavily on [effective_resources](https://github.com/code-and-effect/effective_resources) which is a dependency of this gem. I would also recommend you install [effective_developer](https://github.com/code-and-effect/effective_developer) to get access to some scaffolds and generators. It's not required but I'm gonna use them in this example.
944
+
945
+ Here is how I build rails models for inline datatable CRUD operations:
946
+
947
+ 1. Create a new model file `app/models/thing.rb`:
948
+
949
+ ```ruby
950
+ class Thing < ApplicationRecord
951
+ belongs_to :user
952
+
953
+ effective_resource do
954
+ title :string
955
+ description :text
956
+ timestamps
957
+ end
958
+
959
+ scope :deep, -> { includes(:user) }
960
+ scope :sorted, -> { order(:title) }
961
+
962
+ def to_s
963
+ title
964
+ end
965
+ end
966
+ ```
967
+
968
+ The `effective_resource do` block comes from the [effective_resources](https://github.com/code-and-effect/effective_resources) gem and is used to build any permitted_params.
969
+
970
+ 2. Generate a migration. Run `rails generate effective:migration things` to create a migration based off the model file then `rails db:migrate`.
971
+
972
+ 3. Scaffold the rest. Run `rails generate effective:scaffold_controller things` which will create:
973
+
974
+ - A controller `app/controllers/things_controller.rb`:
975
+
976
+ ```ruby
977
+ class ThingsController < ApplicationController
978
+ include Effective::CrudController
979
+ end
980
+ ```
981
+
982
+ The Effective::CrudController comes from [effective_resources](https://github.com/code-and-effect/effective_resources) gem and handles the standard 7 CRUD actions and member and collection actions. It is opinionated code that follows rails conventions. It considers the `routes.rb` and `ability.rb` or other authorization, to find all available actions.
983
+
984
+ - A datatable `app/datatables/things_datatable.rb`:
985
+
986
+ ```ruby
987
+ class ThingsDatatable < Effective::Datatable
988
+ datatable do
989
+ col :title
990
+ col :description
991
+ actions_col
992
+ end
993
+
994
+ collection do
995
+ Thing.deep.all
996
+ end
997
+ end
998
+ ```
999
+
1000
+ This is an ordinary datatable. As long as it's an ActiveRecord collection, inline crud will work.
1001
+
1002
+ - A view partial `app/views/things/_thing.html.haml`:
1003
+
1004
+ ```ruby
1005
+ %table.table
1006
+ %tbody
1007
+ %tr
1008
+ %th Title
1009
+ %td= thing.title
1010
+ %tr
1011
+ %th Description
1012
+ %td= thing.description
1013
+ ```
1014
+
1015
+ This file is what rails uses when you call `render(thing)` and what datatables uses for the inline `show` action. It's important that its called `_thing.html`.
1016
+
1017
+ - A form partial `app/views/things/_form.html.haml`:
1018
+
1019
+ ```ruby
1020
+ = effective_form_with(model: thing) do |f|
1021
+ = f.text_field :title
1022
+ = f.text_area :description
1023
+ = f.submit
1024
+ ```
1025
+
1026
+ The `effective_form_with` comes from [effective_bootstrap](https://github.com/code-and-effect/effective_bootstrap) gem and is a drop-in replacement for the newer `form_with` syntax. It's really good, you should use it, but an ordinary `form_with` will work here just fine.
1027
+
1028
+ This `_form.html` is an effective gems convention. This file must exist for your resource.
1029
+
1030
+ - A resources entry in `config/routes.rb`:
1031
+
1032
+ ```ruby
1033
+ Rails.application.routes.draw do
1034
+ resources :things do
1035
+ post :approve, on: :member
1036
+ post :reject, on: :member
1037
+ end
1038
+ end
1039
+ ```
1040
+
1041
+ Above we have `resources :things` for the 7 crud actions. And we add two more member actions, which datatables will call `approve!` or `reject!` on thing.
1042
+
1043
+
1044
+ 4. Render in the view. Create an `app/views/things/index.html.haml` and call `render_datatable(@datatable, inline: true)` or `render_inline_datatable(@datatable).
1045
+
1046
+ ```ruby
1047
+ = render_datatable(@datatable, inline: true)
1048
+ ```
1049
+
1050
+ Your datatable should now have New, Show, Edit, Approve and Reject buttons. Click them for inline functionality.
1051
+
1052
+ ## Troubleshooting Inline
1053
+
1054
+ If things aren't working, try the following:
1055
+
1056
+ - Double check your javascripts:
1057
+
1058
+ ```ruby
1059
+ //= require jquery3
1060
+ //= require popper
1061
+ //= require bootstrap
1062
+ //= require effective_bootstrap
1063
+ //= require effective_datatables
1064
+ //= require jquery_ujs
1065
+ ```
1066
+
1067
+ The inline functionality requires one of sprockets jquery_ujs, sprockets rails_ujs or webpack @rails/ujs libraries.
1068
+
1069
+ - Double check your stylesheets:
1070
+
1071
+ ```ruby
1072
+ @import 'bootstrap';
1073
+ @import 'effective_bootstrap';
1074
+ @import 'effective_datatables';
1075
+ ```
1076
+
1077
+ - Make sure your datatable is not being rendered inside a `<form>...</form>` tag. It will display a javascript console error and won't work.
1078
+
1079
+ - Double check your `resources :things` are in `routes.rb` in the same namespace as the controller, and that you have authorization for those actions in `ability.rb` or whatever your `config/initializers/effective_datatables.rb` `config.authorization_method` returns.
1080
+
1081
+ ## A note on how it works
1082
+
1083
+ We use good old `rails_ujs` for all inline actions.
1084
+
1085
+ When inline, any of the actions_col actions, as well as the New button, will be changed into `data-remote: true` actions.
1086
+
1087
+ The [inline_crud javascript](https://github.com/code-and-effect/effective_datatables/blob/master/app/assets/javascripts/effective_datatables/inline_crud.js.coffee) handles fetching the form, or view partial and expanding/collapsing the appropriate row of the datatable.
1088
+
1089
+ When an inline action is clicked, effective_datatables will make an AJAX request to the server, which could be received by an `Effective::CrudController` that will handle the `.js` format, and respond_with the appropriate [rails_ujs .js.erb views](https://github.com/code-and-effect/effective_resources/tree/master/app/views/application).
1090
+
1091
+
1092
+ # Extras
934
1093
 
935
1094
  The following commands don't quite fit into the DSL, but are present nonetheless.
936
1095
 
937
- ### simple
1096
+ ## simple
938
1097
 
939
1098
  To render a simple table, without pagination, sorting, filtering, export buttons, per page, and default visibility:
940
1099
 
@@ -942,7 +1101,7 @@ To render a simple table, without pagination, sorting, filtering, export buttons
942
1101
  <%= render_datatable(@datatable, simple: true) %>
943
1102
  ```
944
1103
 
945
- ### index
1104
+ ## index
946
1105
 
947
1106
  If you just want to render a datatable and nothing else, there is a quick way to skip creating a view:
948
1107
 
@@ -956,13 +1115,13 @@ end
956
1115
 
957
1116
  will render `views/effective/datatables/index` with the assigned datatable.
958
1117
 
959
- ## Advanced Search and Sort
1118
+ # Advanced Search and Sort
960
1119
 
961
1120
  The built-in search and ordering can be overridden on a per-column basis.
962
1121
 
963
1122
  The only gotcha here is that you must be aware of the type of collection.
964
1123
 
965
- ### With ActiveRecord collection
1124
+ ## With ActiveRecord collection
966
1125
 
967
1126
  In the case of a `col` and an ActiveRecord collection:
968
1127
 
@@ -994,7 +1153,7 @@ If `column[:sql_column].blank?` then this `col` has fallen back to being a `val`
994
1153
 
995
1154
  Try adding `col :post_category, sql_column: 'post_categories.title'`
996
1155
 
997
- ### With Array collection
1156
+ ## With Array collection
998
1157
 
999
1158
  And in the case of a `col` with an Array collection, or any `val`:
1000
1159
 
@@ -1033,7 +1192,7 @@ end
1033
1192
 
1034
1193
  The search and sort for each column will be merged together to form the final results.
1035
1194
 
1036
- ### Default search collection
1195
+ ## Default search collection
1037
1196
 
1038
1197
  When using a `col :comments` type belongs_to or has_many column, a search collection for that class will be loaded.
1039
1198
 
@@ -1155,6 +1314,22 @@ def finalize(collection)
1155
1314
  end
1156
1315
  ```
1157
1316
 
1317
+ ## Render outside of view
1318
+
1319
+ You can render a datatable outside the view.
1320
+
1321
+ Anything you pass to the `rendered` method is treated as view/request params.
1322
+
1323
+ You can test filters and scopes by passing them here.
1324
+
1325
+ ```
1326
+ post = Post.create!
1327
+ datatable = PostsDatatable.new.rendered(end_date: Time.zone.now+2.days, current_user_id: 1)
1328
+
1329
+ assert_equal 1, datatable.collection.count
1330
+ assert_equal [post], datatable.collection
1331
+ ```
1332
+
1158
1333
  ## Authorization
1159
1334
 
1160
1335
  All authorization checks are handled via the config.authorization_method found in the `config/initializers/effective_datatables.rb` file.
@@ -16,7 +16,7 @@ flash = (message, status = '') ->
16
16
  timeout = $processing.data('timeout')
17
17
  clearTimeout(timeout) if timeout
18
18
 
19
- delay = (if status == 'danger' then 4000 else 1500)
19
+ delay = (if status == 'danger' then 4000 else 1000)
20
20
 
21
21
  $processing.html(message).data('timeout', setTimeout( =>
22
22
  $processing.html('Processing...')
@@ -5,6 +5,9 @@ initializeDataTables = (target) ->
5
5
  buttons_export_columns = options['buttons_export_columns'] || ':not(.col-actions)'
6
6
  reorder = datatable.data('reorder')
7
7
 
8
+ if datatable.data('inline') && datatable.closest('form').length > 0
9
+ console.error('inline datatable cannot work inside a form')
10
+
8
11
  if options['buttons'] == false
9
12
  options['buttons'] = []
10
13
 
@@ -49,7 +52,7 @@ initializeDataTables = (target) ->
49
52
  displayStart: datatable.data('display-start')
50
53
  iDisplayLength: datatable.data('display-length')
51
54
  language: datatable.data('language')
52
- lengthMenu: [[5, 10, 25, 50, 100, 250, 500, 9999999], ['5', '10', '25', '50', '100', '250', '500', 'All']]
55
+ lengthMenu: [[5, 10, 25, 50, 100, 250, 500, 9999999], ['5', '10', '25', '50', '100', '250', '500', datatable.data('all-label')]]
53
56
  order: datatable.data('display-order')
54
57
  processing: true
55
58
  responsive: true
@@ -77,7 +80,7 @@ initializeDataTables = (target) ->
77
80
  filter_name = name.replace('filters[', '').substring(0, name.length-9)
78
81
 
79
82
  params['filter'][filter_name] = $form.find("input[name='#{name}']:checked").val()
80
-
83
+
81
84
  else if $input.attr('id')
82
85
  filter_name = $input.attr('id').replace('filters_', '')
83
86
  params['filter'][filter_name] = $input.val()
@@ -162,7 +165,6 @@ initializeDataTables = (target) ->
162
165
  $input.on 'change', (event) -> dataTableSearch($(event.currentTarget))
163
166
  else if $input.is('input')
164
167
  $input.delayedChange ($input) -> dataTableSearch($input)
165
- $input.on('paste', -> dataTableSearch($input))
166
168
 
167
169
  # Do the actual search
168
170
  dataTableSearch = ($input) -> # This is the function called by a select or input to run the search
@@ -172,7 +174,9 @@ initializeDataTables = (target) ->
172
174
 
173
175
  value = $input.val()
174
176
 
175
- if value.startsWith('"') && value.endsWith('"')
177
+ if Array.isArray(value)
178
+ # Nothing
179
+ else if value.startsWith('"') && value.endsWith('"')
176
180
  value = value.substring(1, value.length-1)
177
181
  else
178
182
  value = $.trim(value)
@@ -196,6 +200,7 @@ initializeDataTables = (target) ->
196
200
 
197
201
  table.addClass('initialized')
198
202
  table.children('thead').trigger('effective-bootstrap:initialize')
203
+ table.children('thead').find('input[autofocus]').first().focus()
199
204
  true
200
205
 
201
206
  destroyDataTables = ->
@@ -1,15 +1,34 @@
1
1
  # To achieve inline crud, we use rails' data-remote links, and override their behaviour when inside a datatable
2
2
  # This works with EffectiveForm.remote_form which is part of the effective_bootstrap gem.
3
3
 
4
- # We click the New/Edit/Action button from the col-actions
5
- $(document).on 'ajax:beforeSend', '.dataTables_wrapper .col-actions', (e, xhr, settings) ->
6
- $action = $(e.target)
7
- $table = $(e.target).closest('table')
4
+ # https://github.com/rails/jquery-ujs/wiki/ajax
5
+ # https://edgeguides.rubyonrails.org/working_with_javascript_in_rails.html#rails-ujs-event-handlers
6
+
7
+ $(document).on 'ajax:before', '.dataTables_wrapper .col-actions', (event) ->
8
+ $action = $(event.target)
9
+ $table = $(event.target).closest('table')
8
10
 
9
11
  return true if ('' + $action.data('inline')) == 'false'
10
12
 
11
- $params = $.param({_datatable_id: $table.attr('id'), _datatable_attributes: $table.data('attributes'), _datatable_action: true })
12
- settings.url += (if settings.url.indexOf('?') == -1 then '?' else '&') + $params
13
+ $params = $.param(
14
+ {
15
+ _datatable_id: $table.attr('id'),
16
+ _datatable_attributes: $table.data('attributes'),
17
+ _datatable_action: true
18
+ }
19
+ )
20
+
21
+ $action.attr('data-params', $params)
22
+ true
23
+
24
+ # We click the New/Edit/Action button from the col-actions
25
+ $(document).on 'ajax:beforeSend', '.dataTables_wrapper .col-actions', (event, xhr, settings) ->
26
+ [xhr, settings] = event.detail if event.detail # rails/ujs
27
+
28
+ $action = $(event.target)
29
+ $table = $(event.target).closest('table')
30
+
31
+ return true if ('' + $action.data('inline')) == 'false'
13
32
 
14
33
  if $action.closest('.effective-datatables-inline-row,table.dataTable').hasClass('effective-datatables-inline-row')
15
34
  # Nothing.
@@ -22,6 +41,8 @@ $(document).on 'ajax:beforeSend', '.dataTables_wrapper .col-actions', (e, xhr, s
22
41
 
23
42
  # We have either completed the resource action, or fetched the inline form to load.
24
43
  $(document).on 'ajax:success', '.dataTables_wrapper .col-actions', (event, data) ->
44
+ [data, status, xhr] = event.detail if event.detail # rails/ujs
45
+
25
46
  $action = $(event.target)
26
47
 
27
48
  return true if ('' + $action.data('inline')) == 'false'
@@ -54,12 +75,22 @@ $(document).on 'ajax:error', '.dataTables_wrapper', (event) ->
54
75
  EffectiveForm.remote_form_flash = ''
55
76
  true
56
77
 
57
- # Submitting an inline datatables form
58
- $(document).on 'ajax:beforeSend', '.dataTables_wrapper .col-inline-form', (e, xhr, settings) ->
59
- $table = $(e.target).closest('table')
78
+ ## Now for the fetched form. We add the datatables params attributes
79
+
80
+ $(document).on 'ajax:before', '.dataTables_wrapper .col-inline-form', (event) ->
81
+ $action = $(event.target)
82
+ $form = $action.closest('form')
83
+ $table = $action.closest('table')
84
+
85
+ if $form.find('input[name=_datatable_id]').length == 0
86
+ $('<input>').attr(
87
+ {type: 'hidden', name: '_datatable_id', value: $table.attr('id')}
88
+ ).appendTo($form)
60
89
 
61
- $params = $.param({_datatable_id: $table.attr('id'), _datatable_attributes: $table.data('attributes') })
62
- settings.url += (if settings.url.indexOf('?') == -1 then '?' else '&') + $params
90
+ if $form.find('input[name=_datatable_attributes]').length == 0
91
+ $('<input>').attr(
92
+ {type: 'hidden', name: '_datatable_attributes', value: $table.data('attributes')}
93
+ ).appendTo($form)
63
94
 
64
95
  true
65
96
 
@@ -92,7 +123,6 @@ beforeNew = ($action) ->
92
123
 
93
124
  # Append spinner and show Processing
94
125
  $th.append($table.data('spinner'))
95
- $table.DataTable().flash()
96
126
  $table.one 'draw.dt', (event) ->
97
127
  $th.find('a').show().siblings('svg').remove() if event.target == event.currentTarget
98
128
 
@@ -121,7 +151,6 @@ beforeEdit = ($action) ->
121
151
 
122
152
  # Append spinner and show Processing
123
153
  $td.append($table.data('spinner'))
124
- $table.DataTable().flash()
125
154
 
126
155
  afterEdit = ($action) ->
127
156
  $tr = $action.closest('tr')
@@ -8,7 +8,14 @@ reorder = (event, diff, edit) ->
8
8
  return unless oldNode? && newNode?
9
9
 
10
10
  url = @context[0].ajax.url.replace('.json', '/reorder.json')
11
- data = {'reorder[id]': oldNode.data('reorder-resource'), 'reorder[old]': oldNode.val(), 'reorder[new]': newNode.val(), attributes: $table.data('attributes') }
11
+
12
+ data = {
13
+ 'authenticity_token': $('head').find("meta[name='csrf-token']").attr('content'),
14
+ 'reorder[id]': oldNode.data('reorder-resource'),
15
+ 'reorder[old]': oldNode.val(),
16
+ 'reorder[new]': newNode.val(),
17
+ 'attributes': $table.data('attributes')
18
+ }
12
19
 
13
20
  @context[0].rowreorder.c.enable = false
14
21
 
@@ -40,4 +47,3 @@ $(document).on 'click', '.dataTables_wrapper a.buttons-reorder', (event) ->
40
47
  $table.addClass('reordering')
41
48
 
42
49
  column.visible(!column.visible())
43
-
@@ -14,7 +14,7 @@
14
14
 
15
15
  return this.each(function() {
16
16
  var element = $(this);
17
- element.keyup(function() {
17
+ element.on('keyup paste', function() {
18
18
  clearTimeout(timer);
19
19
  timer = setTimeout(function() {
20
20
  var newVal = element.val();
@@ -162,9 +162,7 @@ div.dataTables_scrollFoot > .dataTables_scrollFootInner > table {
162
162
  text-align: center;
163
163
  }
164
164
  }
165
- table.dataTable.table-sm > thead > tr > th {
166
- padding-right: 20px;
167
- }
165
+
168
166
  table.dataTable.table-sm .sorting:before,
169
167
  table.dataTable.table-sm .sorting_asc:before,
170
168
  table.dataTable.table-sm .sorting_desc:before {
@@ -1,6 +1,6 @@
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, pagination: true, search: true, simple: false, sort: true)
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)
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
 
@@ -10,6 +10,7 @@ module EffectiveDatatablesHelper
10
10
 
11
11
  datatable.attributes[:inline] = true if inline
12
12
  datatable.attributes[:sortable] = false unless sort
13
+ datatable.attributes[:namespace] = namespace if namespace
13
14
 
14
15
  datatable.view ||= self
15
16
 
@@ -40,6 +41,7 @@ module EffectiveDatatablesHelper
40
41
  id: datatable.to_param,
41
42
  class: html_class,
42
43
  data: {
44
+ 'all-label' => I18n.t('effective_datatables.all'),
43
45
  'attributes' => EffectiveDatatables.encrypt(datatable.attributes),
44
46
  'authenticity-token' => form_authenticity_token,
45
47
  'bulk-actions' => datatable_bulk_actions(datatable),
@@ -44,7 +44,7 @@ module EffectiveDatatablesPrivateHelper
44
44
  action = { action: :new, class: ['btn', column[:btn_class].presence].compact.join(' '), 'data-remote': true }
45
45
 
46
46
  if column[:actions][:new].kind_of?(Hash) # This might be active_record_array_collection?
47
- action = action.merge(column[:actions][:new])
47
+ action.merge!(column[:actions][:new])
48
48
 
49
49
  effective_resource = (datatable.effective_resource || datatable.fallback_effective_resource)
50
50
  klass = (column[:actions][:new][:klass] || effective_resource&.klass || datatable.collection_class)
@@ -84,7 +84,7 @@ module EffectiveDatatablesPrivateHelper
84
84
  collection = opts[:search].delete(:collection)
85
85
  value = datatable.state[:search][name]
86
86
 
87
- options = opts[:search].except(:fuzzy).merge!(
87
+ options = opts[:search].merge!(
88
88
  name: nil,
89
89
  feedback: false,
90
90
  label: false,
@@ -92,24 +92,26 @@ module EffectiveDatatablesPrivateHelper
92
92
  data: { 'column-name': name, 'column-index': opts[:index] }
93
93
  )
94
94
 
95
+ options.delete(:fuzzy)
96
+
95
97
  case options.delete(:as)
96
98
  when :string, :text, :number
97
99
  form.text_field name, options
98
100
  when :date, :datetime
99
- form.date_field name, options.reverse_merge(
101
+ form.date_field name, options.reverse_merge!(
100
102
  date_linked: false, prepend: false, input_js: { useStrict: true, keepInvalid: true }
101
103
  )
102
104
  when :time
103
- form.time_field name, options.reverse_merge(
105
+ form.time_field name, options.reverse_merge!(
104
106
  date_linked: false, prepend: false, input_js: { useStrict: false, keepInvalid: true }
105
107
  )
106
108
  when :select, :boolean
107
- options[:input_js] = (options[:input_js] || {}).reverse_merge(placeholder: '')
109
+ options[:input_js] = (options[:input_js] || {}).reverse_merge!(placeholder: '')
108
110
 
109
111
  form.select name, collection, options
110
112
  when :bulk_actions
111
113
  options[:data]['role'] = 'bulk-actions'
112
- form.check_box name, options.merge(label: '&nbsp;')
114
+ form.check_box name, options.merge!(label: '&nbsp;')
113
115
  end
114
116
  end
115
117
 
@@ -139,7 +141,7 @@ module EffectiveDatatablesPrivateHelper
139
141
  placeholder: (opts[:label] || name.to_s.titleize),
140
142
  value: value,
141
143
  wrapper: { class: 'form-group col-auto'}
142
- }.merge(opts.except(:as, :collection, :parse, :value))
144
+ }.merge!(opts.except(:as, :collection, :parse, :value))
143
145
 
144
146
  options[:name] = '' unless datatable._filters_form_required?
145
147
 
@@ -149,6 +151,8 @@ module EffectiveDatatablesPrivateHelper
149
151
  elsif as == :boolean
150
152
  collection ||= [true, false].map { |value| [t("effective_datatables.boolean_#{value}"), value] }
151
153
  form.public_send(:select, name, collection, options) # boolean
154
+ elsif as == :string
155
+ form.public_send(:text_field, name, options)
152
156
  elsif form.respond_to?(as)
153
157
  form.public_send(as, name, options) # check_box, text_area
154
158
  else
@@ -169,7 +173,7 @@ module EffectiveDatatablesPrivateHelper
169
173
  label: false,
170
174
  required: false,
171
175
  wrapper: { class: 'form-group col-auto'}
172
- }.merge(opts.except(:checked, :value))
176
+ }.merge!(opts.except(:checked, :value))
173
177
 
174
178
  form.radios :scope, collection, options
175
179
  end
@@ -1,8 +1,8 @@
1
1
  module Effective
2
2
  class Datatable
3
3
  attr_reader :attributes # Anything that we initialize our table with. That's it. Can't be changed by state.
4
- attr_reader :effective_resource
5
4
  attr_reader :state
5
+ attr_accessor :effective_resource
6
6
 
7
7
  # Hashes of DSL options
8
8
  attr_reader :_aggregates
@@ -53,10 +53,36 @@ module Effective
53
53
  self.view = view if view
54
54
  end
55
55
 
56
+ def rendered(params = {})
57
+ raise('expected a hash of params') unless params.kind_of?(Hash)
58
+
59
+ view = ApplicationController.renderer.controller.helpers
60
+
61
+ view.class_eval do
62
+ attr_accessor :rendered_params
63
+
64
+ def current_user
65
+ rendered_params[:current_user]
66
+ end
67
+ end
68
+
69
+ if params[:current_user_id]
70
+ params[:current_user] = User.find(params[:current_user_id])
71
+ end
72
+
73
+ view.rendered_params = params
74
+
75
+ self.view = view
76
+ self
77
+ end
78
+
56
79
  # Once the view is assigned, we initialize everything
57
80
  def view=(view)
58
81
  @view = (view.respond_to?(:view_context) ? view.view_context : view)
59
- raise 'expected view to respond to params' unless @view.respond_to?(:params)
82
+
83
+ unless @view.respond_to?(:params) || @view.respond_to?(:rendered_params)
84
+ raise 'expected view to respond to params'
85
+ end
60
86
 
61
87
  assert_attributes!
62
88
  load_attributes!
@@ -187,9 +187,3 @@ module Effective
187
187
 
188
188
  end
189
189
  end
190
-
191
- # [
192
- # [1, 'title 1'],
193
- # [2, 'title 2'],
194
- # [3, 'title 3']
195
- # ]
@@ -11,6 +11,7 @@ module Effective
11
11
  end
12
12
 
13
13
  def load_attributes!
14
+ return unless view.respond_to?(:controller_path)
14
15
  @attributes[:namespace] ||= view.controller_path.split('/')[0...-1].join('/')
15
16
  end
16
17
 
@@ -64,6 +64,7 @@ module Effective
64
64
  if state[:visible][name] == false && (name != order_name) # Sort by invisible array column
65
65
  BLANK
66
66
  elsif opts[:compute]
67
+
67
68
  if array_collection?
68
69
  dsl_tool.instance_exec(obj, obj[opts[:index]], &opts[:compute])
69
70
  else
@@ -10,6 +10,7 @@ module Effective
10
10
 
11
11
  def load_cookie!
12
12
  return unless EffectiveDatatables.save_state
13
+ return unless view.respond_to?(:cookies)
13
14
 
14
15
  @dt_cookie = view.cookies.signed['_effective_dt']
15
16
 
@@ -33,6 +34,7 @@ module Effective
33
34
 
34
35
  def save_cookie!
35
36
  return unless EffectiveDatatables.save_state
37
+ return unless view.respond_to?(:cookies)
36
38
 
37
39
  @dt_cookie ||= []
38
40
  @dt_cookie << [cookie_key, cookie_payload]
@@ -20,7 +20,7 @@ module Effective
20
20
  elsif value != nil
21
21
  Effective::Attribute.new(value).type
22
22
  end
23
- ) || :text
23
+ ) || :string
24
24
 
25
25
  datatable._filters[name.to_sym] = {
26
26
  value: value,
@@ -16,7 +16,7 @@ module Effective
16
16
  next unless state[:visible][name]
17
17
 
18
18
  if opts[:partial]
19
- locals = { datatable: self, column: opts }.merge(resource_col_locals(opts))
19
+ locals = { datatable: self, column: opts }.merge!(resource_col_locals(opts))
20
20
 
21
21
  rendered[name] = (view.render(
22
22
  partial: opts[:partial],
@@ -27,7 +27,6 @@ module Effective
27
27
  spacer_template: SPACER_TEMPLATE
28
28
  ) || '').split(SPACER)
29
29
  elsif opts[:as] == :actions # This is actions_col and actions_col do .. end, but not actions_col partial: 'something'
30
- resources = collection.map { |row| row[opts[:index]] }
31
30
  locals = { datatable: self, column: opts, spacer_template: SPACER_TEMPLATE }
32
31
 
33
32
  atts = {
@@ -36,16 +35,17 @@ module Effective
36
35
  effective_resource: effective_resource,
37
36
  locals: locals,
38
37
  partial: opts[:actions_partial],
39
- }.compact.merge(opts[:actions])
38
+ }.merge!(opts[:actions]).tap(&:compact!)
40
39
 
41
40
  rendered[name] = if effective_resource.blank?
42
- resources.map do |resource|
41
+ collection.map { |row| row[opts[:index]] }.map do |resource|
43
42
  polymorphic_resource = Effective::Resource.new(resource, namespace: controller_namespace)
44
43
  (view.render_resource_actions(resource, atts.merge(effective_resource: polymorphic_resource), &opts[:format]) || '')
45
44
  end
46
45
  else
47
- (view.render_resource_actions(resources, atts, &opts[:format]) || '').split(SPACER)
46
+ (view.render_resource_actions(collection.map { |row| row[opts[:index]] }, atts, &opts[:format]) || '').split(SPACER)
48
47
  end
48
+
49
49
  end
50
50
  end
51
51
 
@@ -88,9 +88,9 @@ module Effective
88
88
  when :currency
89
89
  view.number_to_currency(value)
90
90
  when :date
91
- (value.strftime('%F') rescue BLANK)
91
+ value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_date) : BLANK
92
92
  when :datetime
93
- (value.strftime('%F %H:%M') rescue BLANK)
93
+ value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_datetime) : BLANK
94
94
  when :decimal
95
95
  value
96
96
  when :duration
@@ -116,7 +116,7 @@ module Effective
116
116
  when Numeric ; view.number_to_currency(value)
117
117
  end
118
118
  when :time
119
- (value.strftime('%H:%M') rescue BLANK)
119
+ value.respond_to?(:strftime) ? value.strftime(EffectiveDatatables.format_time) : BLANK
120
120
  else
121
121
  value.to_s
122
122
  end
@@ -135,7 +135,7 @@ module Effective
135
135
  end
136
136
 
137
137
  # Merge local options. Special behaviour for remote: false
138
- if column[:actions].kind_of?(Hash) && column[:actions].present?
138
+ if column[:actions].present? && column[:actions].kind_of?(Hash)
139
139
  column[:actions].each do |action, opts|
140
140
  next unless opts.kind_of?(Hash)
141
141
 
@@ -6,18 +6,23 @@ module Effective
6
6
 
7
7
  def datatables_ajax_request?
8
8
  return @_datatables_ajax_request unless @_datatables_ajax_request.nil?
9
+ return unless view.respond_to?(:params)
9
10
 
10
11
  @_datatables_ajax_request = (view.present? && view.params.key?(:draw) && view.params.key?(:columns))
11
12
  end
12
13
 
13
14
  def datatables_inline_request?
14
15
  return @_datatables_inline_request unless @_datatables_inline_request.nil?
16
+ return unless view.respond_to?(:params)
15
17
 
16
18
  @_datatables_inline_request = (view.present? && view.params[:_datatable_id].to_s.split('-')[0...-1] == to_param.split('-')[0...-1])
17
19
  end
18
20
 
19
21
  def params
20
22
  return {} unless view.present?
23
+ return view.rendered_params if view.respond_to?(:rendered_params)
24
+ return {} unless view.respond_to?(:request)
25
+
21
26
  @params ||= {}.tap do |params|
22
27
  Rack::Utils.parse_query(URI(view.request.referer.presence || '/').query).each { |k, v| params[k.to_sym] = v }
23
28
  view.params.each { |k, v| params[k.to_sym] = v }
@@ -4,7 +4,7 @@ module Effective
4
4
  AGGREGATE_SQL_FUNCTIONS = ['ARRAY_AGG(', 'AVG(', 'COUNT(', 'MAX(', 'MIN(', 'STRING_AGG(', 'SUM(']
5
5
 
6
6
  def admin_namespace?
7
- controller_namespace == 'admin'
7
+ [:admin, 'admin'].include?(controller_namespace)
8
8
  end
9
9
 
10
10
  def controller_namespace
@@ -31,7 +31,7 @@ module Effective
31
31
  end
32
32
 
33
33
  def load_effective_resource!
34
- @effective_resource = if active_record_collection?
34
+ @effective_resource ||= if active_record_collection?
35
35
  Effective::Resource.new(collection_class, namespace: controller_namespace)
36
36
  end
37
37
  end
@@ -98,9 +98,11 @@ module Effective
98
98
  opts[:sql_as_column] = true if (effective_resource.table && effective_resource.column(name).blank?)
99
99
  end
100
100
 
101
- if opts[:sql_column].present? && AGGREGATE_SQL_FUNCTIONS.any? { |str| opts[:sql_column].to_s.start_with?(str) }
102
- opts[:sql_as_column] = true
101
+ if opts[:sql_column].present?
102
+ sql_column = opts[:sql_column].to_s
103
+ opts[:sql_as_column] = true if AGGREGATE_SQL_FUNCTIONS.any? { |str| sql_column.start_with?(str) }
103
104
  end
105
+
104
106
  end
105
107
  end
106
108
 
@@ -200,6 +202,7 @@ module Effective
200
202
 
201
203
  def load_resource_belongs_tos!
202
204
  return unless active_record_collection?
205
+ return unless @_collection_apply_belongs_to
203
206
 
204
207
  changed = attributes.select do |attribute, value|
205
208
  attribute = attribute.to_s
@@ -210,7 +213,7 @@ module Effective
210
213
  next unless columns[associated]
211
214
 
212
215
  if columns[associated][:as] == :belongs_to
213
- if @_collection_apply_belongs_to && !@_collection.where_values_hash.include?(attribute)
216
+ unless @_collection.where_values_hash.include?(attribute)
214
217
  @_collection = @_collection.where(attribute => value)
215
218
  end
216
219
 
@@ -218,10 +221,8 @@ module Effective
218
221
  elsif columns[associated][:as] == :belongs_to_polymorphic
219
222
  associated_type = attributes["#{associated}_type".to_sym] || raise("Expected #{associated}_type attribute to be present when #{associated}_id is present on a polymorphic belongs to")
220
223
 
221
- if @_collection_apply_belongs_to
222
- if !@_collection.where_values_hash.include?(attribute) && !@_collection.where_values_hash.include?("#{associated}_type")
223
- @_collection = @_collection.where(attribute => value).where("#{associated}_type" => associated_type)
224
- end
224
+ unless @_collection.where_values_hash.include?(attribute) || @_collection.where_values_hash.include?("#{associated}_type")
225
+ @_collection = @_collection.where(attribute => value).where("#{associated}_type" => associated_type)
225
226
  end
226
227
 
227
228
  columns.delete(associated)
@@ -198,7 +198,7 @@ module Effective
198
198
  def parse_filter_value(filter, value)
199
199
  return filter[:parse].call(value) if filter[:parse]
200
200
  return nil if value.blank? && !filter[:required]
201
- Effective::Attribute.new(filter[:value]).parse(value, name: filter[:name])
201
+ Effective::Attribute.new(filter[:as] || filter[:value] || :string).parse(value, name: filter[:name])
202
202
  end
203
203
 
204
204
  def cookie_state_params
@@ -1,4 +1,4 @@
1
1
  - Array(resource.public_send(column[:name])).each do |file|
2
2
  .col-resource_item
3
3
  - title = [file.content_type, number_to_human_size(file.byte_size)].map(&:presence).compact
4
- = link_to(file.filename, url_for(file), title: title)
4
+ = link_to(file.filename, url_for(file), title: title, target: '_blank')
@@ -1,8 +1,9 @@
1
1
  .btn-group.buttons-bulk-actions
2
2
  %button.btn.btn-link.btn-sm.dropdown-toggle{'type': 'button', 'data-toggle': 'dropdown', 'aria-haspopup': true, 'aria-expanded': false, 'disabled': 'disabled'}
3
- Bulk Actions
3
+ = t('effective_datatables.bulk_actions')
4
4
  .dropdown-menu
5
5
  - if datatable._bulk_actions.present?
6
6
  = datatable._bulk_actions.join.html_safe
7
7
  - else
8
- %a.dropdown-item{href: '#'} No bulk actions
8
+ %a.dropdown-item{href: '#'}
9
+ = t('effective_datatables.no_bulk_actions')
@@ -35,8 +35,12 @@ EffectiveDatatables.setup do |config|
35
35
  config.save_state = true
36
36
 
37
37
  # Configure the _effective_dt cookie.
38
- config.cookie_max_size = 2000 # String size. Final byte size is about 1.5 times bigger, after rails signs it
38
+ config.cookie_max_size = 1500 # String size. Final byte size is about 1.5 times bigger, after rails signs it
39
39
  config.cookie_domain = :all # Should usually be :all
40
40
  config.cookie_tld_length = nil # Leave nil to autodetect, or set to probably 2
41
41
 
42
+ # Date formatting
43
+ config.format_datetime = '%F %H:%M'
44
+ config.format_date = '%F'
45
+ config.format_time = '%H:%M'
42
46
  end
@@ -7,6 +7,8 @@ en:
7
7
  new: New
8
8
  actions: Actions
9
9
  bulk_actions: Bulk Actions
10
+ no_bulk_actions: No bulk actions
10
11
  applying: Applying...
11
12
  boolean_true: 'Yes'
12
- boolean_false: 'No'
13
+ boolean_false: 'No'
14
+ all: All
@@ -7,6 +7,8 @@ es:
7
7
  new: Nuevo
8
8
  actions: Acciones
9
9
  bulk_actions: Acciones en masa
10
+ no_bulk_actions: Sin acciones en masa
10
11
  applying: Filtrando...
11
12
  boolean_true: 'Sí'
12
- boolean_false: 'No'
13
+ boolean_false: 'No'
14
+ all: Todo
@@ -7,6 +7,8 @@ nl:
7
7
  new: Nieuwe
8
8
  actions: Acties
9
9
  bulk_actions: Bulkacties
10
+ no_bulk_actions: Geen bulkacties
10
11
  applying: Toepassen...
11
12
  boolean_true: 'Ja'
12
- boolean_false: 'Nee'
13
+ boolean_false: 'Nee'
14
+ all: Te doen
@@ -1,3 +1,3 @@
1
1
  module EffectiveDatatables
2
- VERSION = '4.8.0'.freeze
2
+ VERSION = '4.8.16'.freeze
3
3
  end
@@ -16,6 +16,10 @@ module EffectiveDatatables
16
16
  mattr_accessor :cookie_domain
17
17
  mattr_accessor :cookie_tld_length
18
18
 
19
+ mattr_accessor :format_datetime
20
+ mattr_accessor :format_date
21
+ mattr_accessor :format_time
22
+
19
23
  mattr_accessor :debug
20
24
 
21
25
  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.8.0
4
+ version: 4.8.16
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-03-31 00:00:00.000000000 Z
11
+ date: 2021-02-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -129,11 +129,9 @@ files:
129
129
  - app/assets/stylesheets/effective_datatables.scss
130
130
  - app/assets/stylesheets/effective_datatables/_overrides.bootstrap4.scss
131
131
  - app/controllers/effective/datatables_controller.rb
132
- - app/datatables/effective_style_guide_datatable.rb
133
132
  - app/helpers/effective_datatables_controller_helper.rb
134
133
  - app/helpers/effective_datatables_helper.rb
135
134
  - app/helpers/effective_datatables_private_helper.rb
136
- - app/models/effective/access_denied.rb
137
135
  - app/models/effective/datatable.rb
138
136
  - app/models/effective/datatable_column.rb
139
137
  - app/models/effective/datatable_column_tool.rb
@@ -163,7 +161,6 @@ files:
163
161
  - app/views/effective/datatables/_resource_column.html.haml
164
162
  - app/views/effective/datatables/_spacer_template.html
165
163
  - app/views/effective/datatables/index.html.haml
166
- - app/views/effective/style_guide/_effective_datatables.html.haml
167
164
  - config/effective_datatables.rb
168
165
  - config/locales/en.yml
169
166
  - config/locales/es.yml
@@ -178,7 +175,7 @@ homepage: https://github.com/code-and-effect/effective_datatables
178
175
  licenses:
179
176
  - MIT
180
177
  metadata: {}
181
- post_install_message:
178
+ post_install_message:
182
179
  rdoc_options: []
183
180
  require_paths:
184
181
  - lib
@@ -193,8 +190,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
193
190
  - !ruby/object:Gem::Version
194
191
  version: '0'
195
192
  requirements: []
196
- rubygems_version: 3.0.3
197
- signing_key:
193
+ rubygems_version: 3.1.2
194
+ signing_key:
198
195
  specification_version: 4
199
196
  summary: Uniquely powerful server-side searching, sorting and filtering of any ActiveRecord
200
197
  or Array collection as well as post-rendered content displayed as a frontend jQuery
@@ -1,45 +0,0 @@
1
- class EffectiveStyleGuideDatatable < Effective::Datatable
2
- datatable do
3
- length 10
4
-
5
- col :id
6
- col :material, search: { collection: ['Stainless Steel', 'Copper', 'Cast Iron', 'Composite'] }
7
- col :bowl, search: { collection: ['Single Bowl', 'Double Bowl', 'Triple Bowl'] }
8
- col :name
9
- col :date, as: :date
10
- end
11
-
12
- # Set the permission check to the same as Effective::StyleGuide
13
- def collection_class
14
- defined?(Effective::StyleGuide) ? Effective::StyleGuide : super
15
- end
16
-
17
- collection do
18
- now = Time.zone.now
19
- [
20
- [1, 'Stainless Steel', 'Single Bowl', 'KOHLER Staccato', (now + 1.day)],
21
- [2, 'Stainless Steel', 'Double Bowl', 'KOHLER Vault Undercounter', (now + 1.day)],
22
- [3, 'Stainless Steel', 'Triple Bowl', 'KRAUS All-In-One', (now + 1.day)],
23
- [4, 'Stainless Steel', 'Single Bowl', 'KOHLER Vault Dual Mount', (now + 1.day)],
24
- [5, 'Stainless Steel', 'Single Bowl', 'KRAUS All-In-One Undermount', (now + 2.days)],
25
- [6, 'Stainless Steel', 'Double Bowl', 'Glacier Bay All-in-One', (now + 2.days)],
26
- [7, 'Stainless Steel', 'Single Bowl', 'Elkay Neptune', (now + 2.days)],
27
- [8, 'Copper', 'Single Bowl', 'ECOSINKS Apron Front Dual Mount', (now + 2.days)],
28
- [9, 'Copper', 'Double Bowl', 'ECOSINKS Dual Mount Front Hammered', (now + 2.days)],
29
- [10, 'Copper', 'Triple Bowl', 'Glarier Bay Undermount', (now + 3.days)],
30
- [11, 'Copper', 'Single Bowl', 'Whitehaus Undermount', (now + 3.days)],
31
- [12, 'Copper', 'Double Bowl', 'Belle Foret Apron Front', (now + 3.days)],
32
- [13, 'Copper', 'Double Bowl', 'Pegasus Dual Mount', (now + 3.days)],
33
- [14, 'Cast Iron', 'Double Bowl', 'KOHLER Whitehaven', (now + 3.days)],
34
- [15, 'Cast Iron', 'Triple Bowl', 'KOHLER Hartland', (now + 3.days)],
35
- [16, 'Cast Iron', 'Single Bowl', 'KOHLER Cape Dory Undercounter', (now + 4.days)],
36
- [17, 'Cast Iron', 'Double Bowl', 'KOLER Bakersfield', (now + 4.days)],
37
- [18, 'Cast Iron', 'Double Bowl', 'American Standard Offset', (now + 4.days)],
38
- [19, 'Cast Iron', 'Single Bowl', 'Brookfield Top', (now + 4.days)],
39
- [20, 'Composite', 'Single Bowl', 'Blanco Diamond Undermount', (now + 5.days)],
40
- [21, 'Composite', 'Double Bowl', 'Mont Blanc Waterbrook', (now + 5.days)],
41
- [22, 'Composite', 'Triple Bowl', 'Pegasus Triple Mount', (now + 5.days)],
42
- [23, 'Composite', 'Single Bowl', 'Swanstone Dual Mount', (now + 5.days)]
43
- ]
44
- end
45
- end
@@ -1,17 +0,0 @@
1
- unless defined?(Effective::AccessDenied)
2
- module Effective
3
- class AccessDenied < StandardError
4
- attr_reader :action, :subject
5
-
6
- def initialize(message = nil, action = nil, subject = nil)
7
- @message = message
8
- @action = action
9
- @subject = subject
10
- end
11
-
12
- def to_s
13
- @message || I18n.t(:'unauthorized.default', :default => 'Access Denied')
14
- end
15
- end
16
- end
17
- end
@@ -1 +0,0 @@
1
- = render_datatable(EffectiveStyleGuideDatatable.new)