effective_datatables 4.7.16 → 4.15.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/MIT-LICENSE +1 -1
- data/README.md +278 -24
- data/app/assets/javascripts/effective_datatables/bulk_actions.js.coffee +32 -9
- data/app/assets/javascripts/effective_datatables/download.js.coffee +10 -0
- data/app/assets/javascripts/effective_datatables/flash.js.coffee +1 -1
- data/app/assets/javascripts/effective_datatables/initialize.js.coffee +22 -13
- data/app/assets/javascripts/effective_datatables/inline_crud.js.coffee +42 -13
- data/app/assets/javascripts/effective_datatables/reorder.js.coffee +8 -2
- data/app/assets/javascripts/effective_datatables/reset.js.coffee +23 -2
- data/app/assets/javascripts/vendor/jquery.delayedChange.js +1 -2
- data/app/assets/stylesheets/dataTables/dataTables.bootstrap4.scss +1 -3
- data/app/controllers/effective/datatables_controller.rb +34 -0
- data/app/helpers/effective_datatables_controller_helper.rb +2 -0
- data/app/helpers/effective_datatables_helper.rb +22 -6
- data/app/helpers/effective_datatables_private_helper.rb +30 -20
- data/app/models/effective/datatable.rb +57 -4
- data/app/models/effective/datatable_column.rb +2 -0
- data/app/models/effective/datatable_column_tool.rb +5 -3
- data/app/models/effective/datatable_dsl_tool.rb +7 -5
- data/app/models/effective/datatable_value_tool.rb +9 -8
- data/app/models/effective/effective_datatable/attributes.rb +21 -0
- data/app/models/effective/effective_datatable/collection.rb +3 -1
- data/app/models/effective/effective_datatable/compute.rb +11 -7
- data/app/models/effective/effective_datatable/cookie.rb +6 -0
- data/app/models/effective/effective_datatable/csv.rb +71 -0
- data/app/models/effective/effective_datatable/dsl/bulk_actions.rb +3 -1
- data/app/models/effective/effective_datatable/dsl/charts.rb +2 -0
- data/app/models/effective/effective_datatable/dsl/datatable.rb +20 -6
- data/app/models/effective/effective_datatable/dsl/filters.rb +3 -1
- data/app/models/effective/effective_datatable/dsl.rb +7 -3
- data/app/models/effective/effective_datatable/format.rb +52 -24
- data/app/models/effective/effective_datatable/hooks.rb +2 -0
- data/app/models/effective/effective_datatable/params.rb +9 -2
- data/app/models/effective/effective_datatable/resource.rb +26 -13
- data/app/models/effective/effective_datatable/state.rb +4 -2
- data/app/views/effective/datatables/_active_storage_column.html.haml +4 -0
- data/app/views/effective/datatables/_bulk_actions_dropdown.html.haml +3 -2
- data/app/views/effective/datatables/_buttons.html.haml +14 -0
- data/config/effective_datatables.rb +8 -1
- data/config/locales/en.yml +4 -1
- data/config/locales/es.yml +4 -1
- data/config/locales/nl.yml +4 -1
- data/config/routes.rb +1 -0
- data/lib/effective_datatables/engine.rb +6 -4
- data/lib/effective_datatables/version.rb +1 -1
- data/lib/effective_datatables.rb +5 -0
- metadata +11 -10
- data/app/datatables/effective_style_guide_datatable.rb +0 -47
- data/app/models/effective/access_denied.rb +0 -17
- 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:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 97162d77c01d7bc35d4d9bbda9b7f61d815628c7ded32c1c9c8a0a16e630c42f
|
4
|
+
data.tar.gz: 2bd27055dd9822c798373d0f073dc049ce471401cef071d50320a02f03d5c491
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b7a59f37ce683bfb17e6b75715dee88a9125d26380988d7e9db9fd2c7f818e00235ee7418680d3dad90dabcf3c4e991bfb81ca32b7a4b80556573bf722a7e49f
|
7
|
+
data.tar.gz: 11d06c3f01185c4d92248bb40a32e78376eca5ae6bbbbabd5997a9a4a0a52f4d6ce1fb70bca5b6c50aa4ad60fb747b7060b3aaaf39bae0fbb5d51420cfbe9cef
|
data/MIT-LICENSE
CHANGED
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
|
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
|
|
@@ -46,6 +46,7 @@ Please check out [Effective Datatables 3.x](https://github.com/code-and-effect/e
|
|
46
46
|
* [order](#order)
|
47
47
|
* [reorder](#reorder)
|
48
48
|
* [aggregate](#aggregate)
|
49
|
+
* [download](#download)
|
49
50
|
* [filters](#filters)
|
50
51
|
* [scope](#scope)
|
51
52
|
* [filter](#filter)
|
@@ -54,7 +55,8 @@ Please check out [Effective Datatables 3.x](https://github.com/code-and-effect/e
|
|
54
55
|
* [bulk_action](#bulk_action_divider)
|
55
56
|
* [bulk_download](#bulk_download)
|
56
57
|
* [bulk_action_content](#bulk_action_content)
|
57
|
-
* [
|
58
|
+
* [Charts](#charts)
|
59
|
+
* [Inline](#inline)
|
58
60
|
* [Extras](#extras)
|
59
61
|
* [Advanced Search and Sort](#advanced-search-and-sort)
|
60
62
|
* [Addtional Functionality](#additional-functionality)
|
@@ -196,6 +198,13 @@ class PostsDatatable < Effective::Datatable
|
|
196
198
|
# POSTs to the given url with params[:ids], an Array of ids for all selected rows
|
197
199
|
# These actions are assumed to change the underlying collection
|
198
200
|
bulk_action 'Approve all', bulk_approve_posts_path, data: { confirm: 'Approve all selected posts?' }
|
201
|
+
# GETs to the given url. Pass the ids via cookie, encoded in url, or LocalStorage.
|
202
|
+
# These actions are assumed to redirect the user to some other page.
|
203
|
+
bulk_action 'Action 1 | ids encoded in params', action_1_posts_path, data: { method: :get }
|
204
|
+
|
205
|
+
bulk_action 'Action 2 | ids stored in _ids_ field in local storage', action_2_posts_path, data: { 'payload-mode' => 'local-storage', method: :get }
|
206
|
+
|
207
|
+
bulk_action 'Action 3 | ids stored in _ids_ field in a cookie', action_3_posts_path, data: { 'payload-mode' => 'cookie', method: :get }
|
199
208
|
bulk_action_divider
|
200
209
|
bulk_action 'Destroy all', bulk_destroy_posts_path, data: { confirm: 'Destroy all selected posts?' }
|
201
210
|
end
|
@@ -453,7 +462,7 @@ The `datatable do ... end` block configures a table of data.
|
|
453
462
|
|
454
463
|
Initialize the datatable in your controller or view, `@datatable = PostsDatatable.new(self)`, and render it in your view `<%= render_datatable(@datatable) %>`
|
455
464
|
|
456
|
-
|
465
|
+
## col
|
457
466
|
|
458
467
|
This is the main DSL method that you will interact with.
|
459
468
|
|
@@ -526,7 +535,7 @@ You can also use the joined syntax, `col 'user.email'` to create a column for ju
|
|
526
535
|
|
527
536
|
This feature is only working with `belongs_to` and you need to add the `.joins(:user)` to the collection do ... end block yourself.
|
528
537
|
|
529
|
-
|
538
|
+
## val
|
530
539
|
|
531
540
|
Shorthand for value, this command also creates a column on the datatable.
|
532
541
|
|
@@ -548,7 +557,7 @@ This is implemented as a full Array search/sort and is much slower for large dat
|
|
548
557
|
|
549
558
|
The `.format do ... end` block can then be used to apply custom formatting.
|
550
559
|
|
551
|
-
|
560
|
+
## bulk_actions_col
|
552
561
|
|
553
562
|
Creates a column of checkboxes for use with the `bulk_actions` section.
|
554
563
|
|
@@ -558,7 +567,7 @@ Use these checkboxes to select all / none / one or more rows for the `bulk_actio
|
|
558
567
|
|
559
568
|
You can only have one `bulk_actions_col` per datatable.
|
560
569
|
|
561
|
-
|
570
|
+
## actions_col
|
562
571
|
|
563
572
|
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
573
|
|
@@ -596,7 +605,13 @@ Any `data-remote` actions will be hijacked and performed as inline ajax by datat
|
|
596
605
|
|
597
606
|
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
607
|
|
599
|
-
|
608
|
+
If the automatic actions_col aren't being displayed, try setting the namespace directly when calling the table
|
609
|
+
|
610
|
+
```
|
611
|
+
MyApp::UsersTable.new(namespace: :my_app)
|
612
|
+
```
|
613
|
+
|
614
|
+
## length
|
600
615
|
|
601
616
|
Sets the default number of rows per page. Valid lengths are `5`, `10`, `25`, `50`, `100`, `250`, `500`, `:all`
|
602
617
|
|
@@ -606,7 +621,7 @@ When not specified, effective_datatables uses the default as per the `config/ini
|
|
606
621
|
length 100
|
607
622
|
```
|
608
623
|
|
609
|
-
|
624
|
+
## order
|
610
625
|
|
611
626
|
Sets the default order of table rows. The first argument is the column, the second the direction.
|
612
627
|
|
@@ -618,7 +633,7 @@ When not specified, effective_datatables will sort by the first defined column.
|
|
618
633
|
order :created_at, :asc|:desc
|
619
634
|
```
|
620
635
|
|
621
|
-
|
636
|
+
## reorder
|
622
637
|
|
623
638
|
Enables drag-and-drop row re-ordering.
|
624
639
|
|
@@ -636,7 +651,7 @@ reorder :position
|
|
636
651
|
|
637
652
|
Using `reorder` will sort the collection by this field and disable all other column sorting.
|
638
653
|
|
639
|
-
|
654
|
+
## aggregate
|
640
655
|
|
641
656
|
The `aggregate` command inserts a row in the table's `tfoot`.
|
642
657
|
|
@@ -673,6 +688,30 @@ end.aggregate { |values, column| distance_of_time_in_words(values.min, values.ma
|
|
673
688
|
|
674
689
|
In the above example, `values` is an Array containing all row's values for one column at a time.
|
675
690
|
|
691
|
+
## download
|
692
|
+
|
693
|
+
Add a Download button which streams a CSV file containing all rows and columns in the table's collection, ignoring any search, sort or filtering.
|
694
|
+
|
695
|
+
This is an opt-in feature.
|
696
|
+
|
697
|
+
To enable, please set `config.download = true` in your `config/initializers/effective_datatables.rb` file.
|
698
|
+
|
699
|
+
Once enabled, you can disable it on an individual table by:
|
700
|
+
|
701
|
+
```ruby
|
702
|
+
datatable do
|
703
|
+
download false
|
704
|
+
end
|
705
|
+
```
|
706
|
+
|
707
|
+
and you can exclude individual columns from being rendered on the CSV export
|
708
|
+
|
709
|
+
```ruby
|
710
|
+
col :first_name, csv: false
|
711
|
+
```
|
712
|
+
|
713
|
+
The column will still appear in the export, but the contents will be blank.
|
714
|
+
|
676
715
|
## filters
|
677
716
|
|
678
717
|
Creates a single form with fields for each `filter` and a single radio input field for all `scopes`.
|
@@ -681,7 +720,7 @@ The form is submitted by an AJAX POST action, or, in some advanced circumstances
|
|
681
720
|
|
682
721
|
Initialize the datatable in your controller or view, `@datatable = PostsDatatable.new(self)`, and render its filters anywhere with `<%= render_datatable_filters(@datatable) %>`.
|
683
722
|
|
684
|
-
|
723
|
+
## scope
|
685
724
|
|
686
725
|
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
726
|
|
@@ -705,7 +744,7 @@ class Post < ApplicationRecord | ActiveRecord::Base
|
|
705
744
|
end
|
706
745
|
```
|
707
746
|
|
708
|
-
|
747
|
+
## filter
|
709
748
|
|
710
749
|
Each filter has a name and a default/fallback value. If the form is submitted blank, the default values are used.
|
711
750
|
|
@@ -758,7 +797,7 @@ Creates a single dropdown menu with a link to each action, download or content.
|
|
758
797
|
|
759
798
|
Along with this section, you must put a `bulk_actions_col` somewhere in your `datatable do ... end` section.
|
760
799
|
|
761
|
-
|
800
|
+
## bulk_action
|
762
801
|
|
763
802
|
Creates a link that becomes clickable when one or more checkbox/rows are selected as per the `bulk_actions_col` column.
|
764
803
|
|
@@ -771,6 +810,12 @@ You can also specify `data-method: :get` to instead make a `GET` request with th
|
|
771
810
|
```ruby
|
772
811
|
bulk_actions do
|
773
812
|
bulk_action 'Approve all', bulk_approve_posts_path, data: { confirm: 'Approve all selected posts?' }
|
813
|
+
|
814
|
+
bulk_action 'Action 1 | ids encoded in params', action_1_posts_path, data: { method: :get }
|
815
|
+
|
816
|
+
bulk_action 'Action 2 | ids stored in _ids_ field in local storage', action_2_posts_path, data: { 'payload-mode' => 'local-storage', method: :get }
|
817
|
+
|
818
|
+
bulk_action 'Action 3 | ids stored in _ids_ field in a cookie', action_3_posts_path, data: { 'payload-mode' => 'cookie', method: :get }
|
774
819
|
end
|
775
820
|
```
|
776
821
|
|
@@ -780,6 +825,9 @@ In your `routes` file:
|
|
780
825
|
resources :posts do
|
781
826
|
collection do
|
782
827
|
post :bulk_approve
|
828
|
+
get :action_1
|
829
|
+
get :action_2
|
830
|
+
get :action_3
|
783
831
|
end
|
784
832
|
end
|
785
833
|
```
|
@@ -798,6 +846,22 @@ def bulk_approve
|
|
798
846
|
render json: { status: 500, message: 'An error occured while approving a post.' }
|
799
847
|
end
|
800
848
|
end
|
849
|
+
|
850
|
+
def action_1
|
851
|
+
@posts = Post.where(id: params[:ids])
|
852
|
+
|
853
|
+
render :some_partial
|
854
|
+
end
|
855
|
+
|
856
|
+
def action_2
|
857
|
+
@posts = Post.where(id: cookies[:ids].split(','))
|
858
|
+
|
859
|
+
render :some_partial
|
860
|
+
end
|
861
|
+
|
862
|
+
def action_3
|
863
|
+
render :some_partial # and get ids via JS: localStorage.getItem('ids');
|
864
|
+
end
|
801
865
|
```
|
802
866
|
|
803
867
|
or if using [effective_resources](https://github.com/code-and-effect/effective_resources):
|
@@ -814,11 +878,11 @@ def approve!
|
|
814
878
|
end
|
815
879
|
```
|
816
880
|
|
817
|
-
|
881
|
+
## bulk_action_divider
|
818
882
|
|
819
883
|
Inserts a menu divider `<li class='divider' role='separator'></li>`
|
820
884
|
|
821
|
-
|
885
|
+
## bulk_download
|
822
886
|
|
823
887
|
So it turns out there are some http issues with using an AJAX action to download a file.
|
824
888
|
|
@@ -859,7 +923,7 @@ def bulk_export_report
|
|
859
923
|
end
|
860
924
|
```
|
861
925
|
|
862
|
-
|
926
|
+
## bulk_action_content
|
863
927
|
|
864
928
|
Blindly inserts content into the dropdown.
|
865
929
|
|
@@ -873,12 +937,16 @@ end
|
|
873
937
|
|
874
938
|
Don't actually use this.
|
875
939
|
|
876
|
-
|
940
|
+
# Charts
|
877
941
|
|
878
942
|
Create a [Google Chart](https://developers.google.com/chart/interactive/docs/quick_start) based on your searched collection, filters and attributes.
|
879
943
|
|
880
944
|
No javascript required. Just use the `chart do ... end` block and return an Array of Arrays.
|
881
945
|
|
946
|
+
The first collection, `collection` is the raw results as returned from the `collection do` block.
|
947
|
+
|
948
|
+
The second collection, `searched_collection` is the results after the table's search columns have been applied, but irregardless of pagination.
|
949
|
+
|
882
950
|
```ruby
|
883
951
|
charts do
|
884
952
|
chart :breakfast, 'BarChart' do |collection|
|
@@ -894,6 +962,18 @@ charts do
|
|
894
962
|
[date.strftime('%F'), posts.length]
|
895
963
|
end
|
896
964
|
end
|
965
|
+
|
966
|
+
chart :posts_per_user, 'ColumnChart' do |collection, searched_collection|
|
967
|
+
measured_posts = if search.present?
|
968
|
+
["Posts with #{search.map { |k, v| k.to_s + ' ' + v.to_s }.join(',')}", searched_collection.length]
|
969
|
+
else
|
970
|
+
['All Posts', collection.length]
|
971
|
+
end
|
972
|
+
|
973
|
+
[['Posts', 'Count'], measured_posts] +
|
974
|
+
searched_collection.group_by(&:user).map { |user, posts| [user.last_name, posts.length] }
|
975
|
+
end
|
976
|
+
|
897
977
|
end
|
898
978
|
```
|
899
979
|
|
@@ -914,11 +994,169 @@ All options passed to `chart` are used to initialize the chart javascript.
|
|
914
994
|
|
915
995
|
By default, the only package that is loaded is `corechart`, see the `config/initializers/effective_datatables.rb` file to add more packages.
|
916
996
|
|
917
|
-
|
997
|
+
# Inline
|
998
|
+
|
999
|
+
Any datatable can be used as an inline datatable, to create, update and destroy resources without leaving the current page.
|
1000
|
+
|
1001
|
+
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)`.
|
1002
|
+
|
1003
|
+
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)
|
1004
|
+
(only the `thing` data model and `things_datatable` are being used inline)
|
1005
|
+
|
1006
|
+
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.
|
1007
|
+
|
1008
|
+
Here is how I build rails models for inline datatable CRUD operations:
|
1009
|
+
|
1010
|
+
1. Create a new model file `app/models/thing.rb`:
|
1011
|
+
|
1012
|
+
```ruby
|
1013
|
+
class Thing < ApplicationRecord
|
1014
|
+
belongs_to :user
|
1015
|
+
|
1016
|
+
effective_resource do
|
1017
|
+
title :string
|
1018
|
+
description :text
|
1019
|
+
timestamps
|
1020
|
+
end
|
1021
|
+
|
1022
|
+
scope :deep, -> { includes(:user) }
|
1023
|
+
scope :sorted, -> { order(:title) }
|
1024
|
+
|
1025
|
+
def to_s
|
1026
|
+
title
|
1027
|
+
end
|
1028
|
+
end
|
1029
|
+
```
|
1030
|
+
|
1031
|
+
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.
|
1032
|
+
|
1033
|
+
2. Generate a migration. Run `rails generate effective:migration things` to create a migration based off the model file then `rails db:migrate`.
|
1034
|
+
|
1035
|
+
3. Scaffold the rest. Run `rails generate effective:scaffold_controller things` which will create:
|
1036
|
+
|
1037
|
+
- A controller `app/controllers/things_controller.rb`:
|
1038
|
+
|
1039
|
+
```ruby
|
1040
|
+
class ThingsController < ApplicationController
|
1041
|
+
include Effective::CrudController
|
1042
|
+
end
|
1043
|
+
```
|
1044
|
+
|
1045
|
+
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.
|
1046
|
+
|
1047
|
+
- A datatable `app/datatables/things_datatable.rb`:
|
1048
|
+
|
1049
|
+
```ruby
|
1050
|
+
class ThingsDatatable < Effective::Datatable
|
1051
|
+
datatable do
|
1052
|
+
col :title
|
1053
|
+
col :description
|
1054
|
+
actions_col
|
1055
|
+
end
|
1056
|
+
|
1057
|
+
collection do
|
1058
|
+
Thing.deep.all
|
1059
|
+
end
|
1060
|
+
end
|
1061
|
+
```
|
1062
|
+
|
1063
|
+
This is an ordinary datatable. As long as it's an ActiveRecord collection, inline crud will work.
|
1064
|
+
|
1065
|
+
- A view partial `app/views/things/_thing.html.haml`:
|
1066
|
+
|
1067
|
+
```ruby
|
1068
|
+
%table.table
|
1069
|
+
%tbody
|
1070
|
+
%tr
|
1071
|
+
%th Title
|
1072
|
+
%td= thing.title
|
1073
|
+
%tr
|
1074
|
+
%th Description
|
1075
|
+
%td= thing.description
|
1076
|
+
```
|
1077
|
+
|
1078
|
+
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`.
|
1079
|
+
|
1080
|
+
- A form partial `app/views/things/_form.html.haml`:
|
1081
|
+
|
1082
|
+
```ruby
|
1083
|
+
= effective_form_with(model: thing) do |f|
|
1084
|
+
= f.text_field :title
|
1085
|
+
= f.text_area :description
|
1086
|
+
= f.submit
|
1087
|
+
```
|
1088
|
+
|
1089
|
+
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.
|
1090
|
+
|
1091
|
+
This `_form.html` is an effective gems convention. This file must exist for your resource.
|
1092
|
+
|
1093
|
+
- A resources entry in `config/routes.rb`:
|
1094
|
+
|
1095
|
+
```ruby
|
1096
|
+
Rails.application.routes.draw do
|
1097
|
+
resources :things do
|
1098
|
+
post :approve, on: :member
|
1099
|
+
post :reject, on: :member
|
1100
|
+
end
|
1101
|
+
end
|
1102
|
+
```
|
1103
|
+
|
1104
|
+
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.
|
1105
|
+
|
1106
|
+
|
1107
|
+
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).
|
1108
|
+
|
1109
|
+
```ruby
|
1110
|
+
= render_datatable(@datatable, inline: true)
|
1111
|
+
```
|
1112
|
+
|
1113
|
+
Your datatable should now have New, Show, Edit, Approve and Reject buttons. Click them for inline functionality.
|
1114
|
+
|
1115
|
+
## Troubleshooting Inline
|
1116
|
+
|
1117
|
+
If things aren't working, try the following:
|
1118
|
+
|
1119
|
+
- Double check your javascripts:
|
1120
|
+
|
1121
|
+
```ruby
|
1122
|
+
//= require jquery3
|
1123
|
+
//= require popper
|
1124
|
+
//= require bootstrap
|
1125
|
+
//= require effective_bootstrap
|
1126
|
+
//= require effective_datatables
|
1127
|
+
//= require jquery_ujs
|
1128
|
+
```
|
1129
|
+
|
1130
|
+
The inline functionality requires one of sprockets jquery_ujs, sprockets rails_ujs or webpack @rails/ujs libraries.
|
1131
|
+
|
1132
|
+
- Double check your stylesheets:
|
1133
|
+
|
1134
|
+
```ruby
|
1135
|
+
@import 'bootstrap';
|
1136
|
+
@import 'effective_bootstrap';
|
1137
|
+
@import 'effective_datatables';
|
1138
|
+
```
|
1139
|
+
|
1140
|
+
- Make sure your datatable is not being rendered inside a `<form>...</form>` tag. It will display a javascript console error and won't work.
|
1141
|
+
|
1142
|
+
- 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.
|
1143
|
+
|
1144
|
+
## A note on how it works
|
1145
|
+
|
1146
|
+
We use good old `rails_ujs` for all inline actions.
|
1147
|
+
|
1148
|
+
When inline, any of the actions_col actions, as well as the New button, will be changed into `data-remote: true` actions.
|
1149
|
+
|
1150
|
+
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.
|
1151
|
+
|
1152
|
+
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).
|
1153
|
+
|
1154
|
+
|
1155
|
+
# Extras
|
918
1156
|
|
919
1157
|
The following commands don't quite fit into the DSL, but are present nonetheless.
|
920
1158
|
|
921
|
-
|
1159
|
+
## simple
|
922
1160
|
|
923
1161
|
To render a simple table, without pagination, sorting, filtering, export buttons, per page, and default visibility:
|
924
1162
|
|
@@ -926,7 +1164,7 @@ To render a simple table, without pagination, sorting, filtering, export buttons
|
|
926
1164
|
<%= render_datatable(@datatable, simple: true) %>
|
927
1165
|
```
|
928
1166
|
|
929
|
-
|
1167
|
+
## index
|
930
1168
|
|
931
1169
|
If you just want to render a datatable and nothing else, there is a quick way to skip creating a view:
|
932
1170
|
|
@@ -940,13 +1178,13 @@ end
|
|
940
1178
|
|
941
1179
|
will render `views/effective/datatables/index` with the assigned datatable.
|
942
1180
|
|
943
|
-
|
1181
|
+
# Advanced Search and Sort
|
944
1182
|
|
945
1183
|
The built-in search and ordering can be overridden on a per-column basis.
|
946
1184
|
|
947
1185
|
The only gotcha here is that you must be aware of the type of collection.
|
948
1186
|
|
949
|
-
|
1187
|
+
## With ActiveRecord collection
|
950
1188
|
|
951
1189
|
In the case of a `col` and an ActiveRecord collection:
|
952
1190
|
|
@@ -978,7 +1216,7 @@ If `column[:sql_column].blank?` then this `col` has fallen back to being a `val`
|
|
978
1216
|
|
979
1217
|
Try adding `col :post_category, sql_column: 'post_categories.title'`
|
980
1218
|
|
981
|
-
|
1219
|
+
## With Array collection
|
982
1220
|
|
983
1221
|
And in the case of a `col` with an Array collection, or any `val`:
|
984
1222
|
|
@@ -1017,7 +1255,7 @@ end
|
|
1017
1255
|
|
1018
1256
|
The search and sort for each column will be merged together to form the final results.
|
1019
1257
|
|
1020
|
-
|
1258
|
+
## Default search collection
|
1021
1259
|
|
1022
1260
|
When using a `col :comments` type belongs_to or has_many column, a search collection for that class will be loaded.
|
1023
1261
|
|
@@ -1139,6 +1377,22 @@ def finalize(collection)
|
|
1139
1377
|
end
|
1140
1378
|
```
|
1141
1379
|
|
1380
|
+
## Render outside of view
|
1381
|
+
|
1382
|
+
You can render a datatable outside the view.
|
1383
|
+
|
1384
|
+
Anything you pass to the `rendered` method is treated as view/request params.
|
1385
|
+
|
1386
|
+
You can test filters and scopes by passing them here.
|
1387
|
+
|
1388
|
+
```
|
1389
|
+
post = Post.create!
|
1390
|
+
datatable = PostsDatatable.new.rendered(end_date: Time.zone.now+2.days, current_user_id: 1)
|
1391
|
+
|
1392
|
+
assert_equal 1, datatable.collection.count
|
1393
|
+
assert_equal [post], datatable.collection
|
1394
|
+
```
|
1395
|
+
|
1142
1396
|
## Authorization
|
1143
1397
|
|
1144
1398
|
All authorization checks are handled via the config.authorization_method found in the `config/initializers/effective_datatables.rb` file.
|
@@ -19,11 +19,12 @@ $(document).on 'change', ".dataTables_wrapper input[data-role='bulk-actions']",
|
|
19
19
|
|
20
20
|
toggleDropdown = ($wrapper) ->
|
21
21
|
$bulkActions = $wrapper.children().first().find('.buttons-bulk-actions').children('button')
|
22
|
+
selected = $wrapper.find("input[data-role='bulk-action']:checked").length
|
22
23
|
|
23
|
-
if
|
24
|
-
$bulkActions.removeAttr('disabled')
|
24
|
+
if selected > 0
|
25
|
+
$bulkActions.removeAttr('disabled').text("Bulk Actions (#{selected} items)")
|
25
26
|
else
|
26
|
-
$bulkActions.attr('disabled', 'disabled')
|
27
|
+
$bulkActions.attr('disabled', 'disabled').text('Bulk Actions')
|
27
28
|
|
28
29
|
restoreSelected = ($table, selected) ->
|
29
30
|
$bulkActions = $table.closest('.dataTables_wrapper').children().first().find('.buttons-bulk-actions').children('button')
|
@@ -41,11 +42,25 @@ restoreSelected = ($table, selected) ->
|
|
41
42
|
|
42
43
|
if present then $bulkActions.removeAttr('disabled') else $bulkActions.attr('disabled', 'disabled')
|
43
44
|
|
44
|
-
|
45
|
+
# rails_ujs data-confirm requires special attention
|
46
|
+
# https://github.com/rails/rails/blob/main/actionview/app/assets/javascripts/rails-ujs/features/confirm.coffee
|
47
|
+
$(document).on 'confirm:complete', '.dataTables_wrapper .buttons-bulk-actions a', (event) ->
|
48
|
+
if event.originalEvent.detail && event.originalEvent.detail[0] == true
|
49
|
+
doBulkActionPost(event)
|
50
|
+
(window.Rails || $.rails).stopEverything(event)
|
51
|
+
return false
|
52
|
+
|
45
53
|
$(document).on 'click', '.dataTables_wrapper .buttons-bulk-actions a', (event) ->
|
46
|
-
event.
|
54
|
+
unless $(event.currentTarget).data('confirm')
|
55
|
+
doBulkActionPost(event)
|
56
|
+
event.preventDefault()
|
57
|
+
|
58
|
+
doBulkActionPost = (event) ->
|
59
|
+
$bulkAction = $(event.currentTarget) # This is the regular <a href=...> tag maybe with data-confirm
|
60
|
+
|
61
|
+
document.cookie = 'ids=; expires=Thu, 01 Jan 1970 00:00:00 GMT'
|
62
|
+
localStorage.removeItem('ids')
|
47
63
|
|
48
|
-
$bulkAction = $(event.currentTarget) # This is a regular <a href=...> tag
|
49
64
|
$wrapper = $bulkAction.closest('.dataTables_wrapper')
|
50
65
|
$table = $wrapper.find('table.dataTable').first()
|
51
66
|
$processing = $table.siblings('.dataTables_processing').first()
|
@@ -54,6 +69,7 @@ $(document).on 'click', '.dataTables_wrapper .buttons-bulk-actions a', (event) -
|
|
54
69
|
url = $bulkAction.attr('href')
|
55
70
|
title = $bulkAction.text()
|
56
71
|
download = $bulkAction.data('bulk-download')
|
72
|
+
payload_mode = $bulkAction.data('payload-mode')
|
57
73
|
token = $table.data('authenticity-token')
|
58
74
|
values = $.map($selected, (input) -> input.getAttribute('value'))
|
59
75
|
method = $bulkAction.data('ajax-method')
|
@@ -61,10 +77,17 @@ $(document).on 'click', '.dataTables_wrapper .buttons-bulk-actions a', (event) -
|
|
61
77
|
return unless url && values
|
62
78
|
|
63
79
|
if method == 'GET'
|
64
|
-
if
|
65
|
-
|
80
|
+
if payload_mode == 'cookie'
|
81
|
+
document.cookie = "ids=#{values}";
|
82
|
+
window.location.assign(url)
|
83
|
+
else if payload_mode == 'local-storage'
|
84
|
+
localStorage.setItem('ids', values);
|
85
|
+
window.location.assign(url)
|
66
86
|
else
|
67
|
-
|
87
|
+
if url.includes('?')
|
88
|
+
window.location.assign(url + '&' + $.param({ids: values}))
|
89
|
+
else
|
90
|
+
window.location.assign(url + '?' + $.param({ids: values}))
|
68
91
|
|
69
92
|
return
|
70
93
|
|
@@ -0,0 +1,10 @@
|
|
1
|
+
$(document).on 'click', '.dataTables_wrapper a.buttons-download', (event) ->
|
2
|
+
$button = $(event.currentTarget)
|
3
|
+
$table = $('#' + $button.attr('aria-controls'))
|
4
|
+
|
5
|
+
url = $table.data('source').replace('.json', '/download.csv')
|
6
|
+
attributes = 'attributes=' + encodeURIComponent($table.data('attributes'))
|
7
|
+
|
8
|
+
$button.attr('href', url + '?' + attributes)
|
9
|
+
|
10
|
+
setTimeout (=> $button.attr('href', 'download.csv')), 0
|
@@ -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
|
19
|
+
delay = (if status == 'danger' then 4000 else 1000)
|
20
20
|
|
21
21
|
$processing.html(message).data('timeout', setTimeout( =>
|
22
22
|
$processing.html('Processing...')
|