effective_datatables 4.8.0 → 4.8.16

Sign up to get free protection for your applications and to get access to all the features.
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)