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