custom_table 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +210 -0
- data/Rakefile +8 -0
- data/app/assets/config/custom_table_manifest.js +1 -0
- data/app/assets/stylesheets/custom_table/application.scss +1 -0
- data/app/assets/stylesheets/custom_table/table.scss +89 -0
- data/app/controllers/concerns/custom_table_concern.rb +118 -0
- data/app/controllers/custom_table/application_controller.rb +4 -0
- data/app/controllers/custom_table/settings_controller.rb +86 -0
- data/app/helpers/custom_table/application_helper.rb +483 -0
- data/app/helpers/custom_table/fieldset_helper.rb +90 -0
- data/app/helpers/custom_table/icons_helper.rb +42 -0
- data/app/inputs/date_picker_input.rb +52 -0
- data/app/javascript/controllers/batch_actions_controller.js +53 -0
- data/app/javascript/controllers/table_controller.js +109 -0
- data/app/jobs/custom_table/application_job.rb +4 -0
- data/app/mailers/custom_table/application_mailer.rb +6 -0
- data/app/models/concerns/custom_table_settings.rb +42 -0
- data/app/models/custom_table/application_record.rb +5 -0
- data/app/views/custom_table/_download.haml +19 -0
- data/app/views/custom_table/_field.haml +8 -0
- data/app/views/custom_table/_field_plain.haml +1 -0
- data/app/views/custom_table/_fieldset.haml +2 -0
- data/app/views/custom_table/_filter.html.haml +104 -0
- data/app/views/custom_table/_settings.html.haml +57 -0
- data/app/views/custom_table/_table.html.haml +261 -0
- data/app/views/custom_table/_table.xlsx.axlsx +76 -0
- data/app/views/custom_table/_table_fe.xlsx.fast_excel +141 -0
- data/app/views/custom_table/_table_row.html.haml +72 -0
- data/app/views/custom_table/_table_row_data.html.haml +26 -0
- data/app/views/custom_table/settings/destroy.html.haml +4 -0
- data/app/views/custom_table/settings/edit.html.haml +2 -0
- data/app/views/custom_table/settings/update.html.haml +4 -0
- data/app/views/layouts/custom_table/application.html.erb +15 -0
- data/config/initializers/simple_form_bootstrap.rb +468 -0
- data/config/locales/en.yml +18 -0
- data/config/locales/ru.yml +18 -0
- data/config/routes.rb +5 -0
- data/lib/custom_table/configuration.rb +10 -0
- data/lib/custom_table/engine.rb +12 -0
- data/lib/custom_table/version.rb +3 -0
- data/lib/custom_table.rb +14 -0
- data/lib/generators/custom_table/USAGE +8 -0
- data/lib/generators/custom_table/custom_table_generator.rb +16 -0
- data/lib/generators/custom_table/templates/initializer.rb +3 -0
- data/lib/generators/custom_table/templates/migration.rb +5 -0
- data/lib/tasks/custom_table_tasks.rake +4 -0
- metadata +300 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 56a21b7978279adb93168f5879fbf85c9953cd90561b3eaffe12fb834039311c
|
4
|
+
data.tar.gz: 5ea82cf638892d34ed8c5dab7dd30c9b4c9d6ea5eacaf954acaa874131dd62dd
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: f0bbd84de0dcd118e79935abf955dc93ddd3161a4871321945644bdf0ce04b14f5705f93e81e68f97f73d602f4ca0fad55dbabcacc06fa10c76501200d619d22
|
7
|
+
data.tar.gz: d3ce8670c0d36f426f129a44a541932210986438657c1eeaaf76c7fe2ebca5f389c2ae958d4b6eb9b5d1d3bfb8d3b75fd2dde19a4413006265ae40136292ca7a
|
data/README.md
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
# Custom Table
|
2
|
+
|
3
|
+
Provides powerful set of functionality for showing tables of data:
|
4
|
+
* Generated table and filter panel for any model
|
5
|
+
* Declare fields that should be displayed, filtered or sorted
|
6
|
+
* Customize visible fields for each user
|
7
|
+
* Exporting table to XLSX
|
8
|
+
|
9
|
+
## Setup
|
10
|
+
|
11
|
+
* Run ```rails generate custom_table install``` to create User migration and Initializer
|
12
|
+
* Generate base helpers
|
13
|
+
* Add CustomTable engine routes
|
14
|
+
* Add concern to controllers
|
15
|
+
* Add CSS import to your application.css: ```@import 'custom_table/table.css';```
|
16
|
+
* Add concern to User model
|
17
|
+
* Declare your first model
|
18
|
+
|
19
|
+
## Declaring fields
|
20
|
+
|
21
|
+
The most important part of using this gem is to correctly declare fields available for showing in table.
|
22
|
+
|
23
|
+
This should be declared in helper named by this pattern:
|
24
|
+
|
25
|
+
```{singular_model_name}_custom_table_fields```
|
26
|
+
|
27
|
+
And shold return hash of field definitions:
|
28
|
+
|
29
|
+
e.g.
|
30
|
+
|
31
|
+
def vegetable_custom_table_fields
|
32
|
+
fields = {}
|
33
|
+
fields[:color] = { search: { q: :color_eq, type: :text }, appear: :default }
|
34
|
+
return fields
|
35
|
+
end
|
36
|
+
|
37
|
+
Use attribute name as key if possbile. Table will try to get most of options automatically from model if you pass regular attribute.
|
38
|
+
|
39
|
+
### Fields declaration options
|
40
|
+
|
41
|
+
* ```label``` adds label to the field. Will try to find human attribute name by default
|
42
|
+
* ```search``` contains search parameters. Skip this if search is not available for this fields
|
43
|
+
* * ```q``` ransack's "q" search marcher which is used to search by the field. For range use array of two elements, e.g. ```[:created_at_gteq, :created_at_lteq]```
|
44
|
+
* * ```type``` type of search element to draw
|
45
|
+
* ```appear``` controls visibility of the field. Default value is hidden if not specially selected
|
46
|
+
* * ```default``` will appear by default
|
47
|
+
* * ```always``` will always appear
|
48
|
+
* * ```export``` will appear only in XLSX export
|
49
|
+
* ```link_to_show``` if true, this fields will have link to show page of item
|
50
|
+
* ```sort``` controls sorting ability for the fields (disabled by default). Use ```true``` or ```{default_order: :asc|:desc}```
|
51
|
+
* ```amount``` if true, applies number-specific formatting to cells (right align)
|
52
|
+
* ```helper``` helper name (will be used instead default, see below)
|
53
|
+
* ```total_scope``` scope which will be applied to collection to count total for rows. By defalt it takes sum(:field)
|
54
|
+
|
55
|
+
## Controller setup
|
56
|
+
|
57
|
+
Add ```CustomTableConcern``` to your controller to get easy index page solution.
|
58
|
+
|
59
|
+
This gem provides custom_table method for your controller which does Ransack search and Kaminari pagination for you:
|
60
|
+
|
61
|
+
def index
|
62
|
+
@q = @vegetables.ransack(params[:q])
|
63
|
+
@q.sorts = 'created_at desc' if @q.sorts.empty? # Sets default sorting for ransack
|
64
|
+
|
65
|
+
@vegetables = @q.result(distict: true)
|
66
|
+
@vegetables = @vegetables.page(params[:page]).per(params[:per] || 25)
|
67
|
+
end
|
68
|
+
|
69
|
+
Is equivalent to:
|
70
|
+
|
71
|
+
def index
|
72
|
+
@vegetables = custom_table(@vegetables)
|
73
|
+
end
|
74
|
+
|
75
|
+
Optional parameters are:
|
76
|
+
|
77
|
+
* ```default_sorts``` - ```string``` sorting order if user not selected it (default to ```created_at desc```)
|
78
|
+
* ```default_query``` - default ransack ```q``` object. Default is empty
|
79
|
+
|
80
|
+
## Rendering tables
|
81
|
+
|
82
|
+
Invoke this in your index to display table:
|
83
|
+
```custom_table_data collection: @vegetables```
|
84
|
+
|
85
|
+
Options available are:
|
86
|
+
|
87
|
+
* Second parameter is variant (can be skipped if you dont use variants)
|
88
|
+
* ```collection``` is the only required option. Contains paged collection from your controller
|
89
|
+
* ```parent``` parent resource for inherited routes
|
90
|
+
* ```skip_fields``` array of field names as symbols. Removes specific fields from table
|
91
|
+
* ```skip_actions``` removes all actions
|
92
|
+
* ```skip_default_actions``` removes default actions
|
93
|
+
* ```actions``` helper name for custom actions. Table also looks for ```{singular_model_name}_custom_table_actions``` helper presence
|
94
|
+
* ```totals``` object of fields to show totals. Use symbols as keys and pass value or left nil to let table try to count total based on raw/field value
|
95
|
+
* ```paginate``` set to false to skip pagination
|
96
|
+
* ```last_page``` set to false to disable last page count request for performance
|
97
|
+
* ```quick_filter``` set to true to enable simple full-text client-side search
|
98
|
+
* ```with_select``` allows to add checkboxes toggler. Pass helper name which has (item, position) as parameters
|
99
|
+
* ```tree``` set to true if you have parent-child relation and you want to show records grouped by parent. Be sure to disable pagination as it will only group current page records
|
100
|
+
* ```group_by``` set to helper name to group records by result of it. Be sure to disable pagination as it will only group current page records
|
101
|
+
* ```expanded``` expand grouped or trees by default
|
102
|
+
|
103
|
+
## Rendering search panel
|
104
|
+
|
105
|
+
Use this helper in order to show filter panel:
|
106
|
+
|
107
|
+
```custom_table_filter search_model: Vegetable```
|
108
|
+
|
109
|
+
Options:
|
110
|
+
|
111
|
+
* ```search_model``` model class to use with this filter. The only required parameter.
|
112
|
+
* ```hide_customization``` hides customization button
|
113
|
+
* ```fields``` if you want to have pre-defined fields, not from model definition
|
114
|
+
|
115
|
+
## Displaying custom fields
|
116
|
+
|
117
|
+
You can declare fields which your model doesn't have. In this case table can't render field value so you have to provide helpers for rendering the field. Table renderer will try to look for these helpers in prioritizing order:
|
118
|
+
|
119
|
+
* ```#{singular_model_name}_#{field}_field``` to avoid naming collisions
|
120
|
+
* ```#{singular_model_name}_#{field}``` best choise for most projects
|
121
|
+
* ```#{singular_model_name}_#{field}_raw``` use this to produce non-decorated raw data which can be used in tables
|
122
|
+
|
123
|
+
If helper is not accessible table will try to render item via following methods:
|
124
|
+
|
125
|
+
* Association via ```to_s``` method
|
126
|
+
* Numeric attribute via ```amount``` helper which formats number
|
127
|
+
* Raw text attributes
|
128
|
+
* Boolean attribute via ```boolean_icon``` helper. Uses bootstrap icons and can be overriden
|
129
|
+
|
130
|
+
If you use variant, following helper will have the priority over all options:
|
131
|
+
* ```#{singular_model_name}_#{variant}_#{field}_field```
|
132
|
+
* ```#{singular_model_name}_#{variant}_#{field}```
|
133
|
+
|
134
|
+
## Displaying custom actions
|
135
|
+
|
136
|
+
|
137
|
+
|
138
|
+
## Customizing user columns
|
139
|
+
|
140
|
+
Add CustomTable as engine to your routes:
|
141
|
+
|
142
|
+
And ```custom_table``` attribute as text to your model
|
143
|
+
|
144
|
+
Search Settings button will show up automatically if you have at least one customizable field.
|
145
|
+
|
146
|
+
You can also use settings button separatelly. It uses Rails turbo and you need to declare ```turbo-modal``` Turbo Tag within your HTML body.
|
147
|
+
|
148
|
+
## Variants
|
149
|
+
|
150
|
+
For each table you can declare additional variants (set of parameters to be saved to user customization).
|
151
|
+
|
152
|
+
Important to note that you need to explicitly set list of available variants. Declare the following helper function:
|
153
|
+
|
154
|
+
```{singular_model_name}_custom_table_fields```
|
155
|
+
|
156
|
+
Which returns the array of available variant.
|
157
|
+
|
158
|
+
Then just pass variant to filter and data helpers.
|
159
|
+
|
160
|
+
## Table Stimulus helper
|
161
|
+
|
162
|
+
|
163
|
+
|
164
|
+
|
165
|
+
## Downloading data as XLSX table
|
166
|
+
|
167
|
+
This gem also provide partial for exporting all available columns as XLSX file via CAXLSX gem:
|
168
|
+
|
169
|
+
wb = xlsx_package.workbook
|
170
|
+
wb.add_worksheet(name: "Aircrafts") do |sheet|
|
171
|
+
render 'custom_table/table', sheet: sheet, collection: @aircrafts.except(:limit, :offset)
|
172
|
+
end
|
173
|
+
|
174
|
+
## Using fieldset helper for show actions
|
175
|
+
|
176
|
+
You can use the same fields declared for table within show views.
|
177
|
+
This also can be used without any table fields declaration and setup.
|
178
|
+
|
179
|
+
The simpliest case here is (haml):
|
180
|
+
|
181
|
+
= fieldset @instance do |fs|
|
182
|
+
= fs.field :name
|
183
|
+
|
184
|
+
It will produce bootstrap fieldset formatting as well as value logic from tables.
|
185
|
+
|
186
|
+
Fieldset formatting can be overriden via views (custom_table/_fieldset and custom_table/field)
|
187
|
+
|
188
|
+
By default fieldset is integrated with ```turbo_editable``` gem and each field is wrapped with it. You can disable it by passing ```editable: false``` as param to fieldset of field.
|
189
|
+
|
190
|
+
Options available are:
|
191
|
+
|
192
|
+
* ```label``` - if it cannot be received via field definition
|
193
|
+
* ```editable_params``` - hash of params to be passed to editable
|
194
|
+
|
195
|
+
All options from fieldset are proxied to field. So you can declare it once if suitable.
|
196
|
+
|
197
|
+
You can declare how each field is displayed. Just add it as block within field:
|
198
|
+
|
199
|
+
= fieldset @instance do |fs|
|
200
|
+
= fs.field :name do
|
201
|
+
= @instance.name.upcase
|
202
|
+
|
203
|
+
## Testing
|
204
|
+
|
205
|
+
Use ```custom_table_use_all_fields``` GET param with any value to show all available fields in your feature tests
|
206
|
+
|
207
|
+
## Development
|
208
|
+
|
209
|
+
Running tests: rspec
|
210
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
//= link_directory ../stylesheets/custom_table .css
|
@@ -0,0 +1 @@
|
|
1
|
+
@import "table.scss";
|
@@ -0,0 +1,89 @@
|
|
1
|
+
|
2
|
+
table.custom-table {
|
3
|
+
|
4
|
+
td.actions {
|
5
|
+
white-space: nowrap;
|
6
|
+
width: 85px;
|
7
|
+
}
|
8
|
+
a.sort_link {
|
9
|
+
text-decoration: none !important;
|
10
|
+
white-space: nowrap;
|
11
|
+
}
|
12
|
+
td.selected {
|
13
|
+
border: 2px solid rgb(26, 179, 26) !important;
|
14
|
+
}
|
15
|
+
|
16
|
+
tr {
|
17
|
+
.action {
|
18
|
+
visibility: hidden;
|
19
|
+
&.btn-sm {
|
20
|
+
padding: 2px 4px !important;
|
21
|
+
}
|
22
|
+
}
|
23
|
+
.d-action-none {
|
24
|
+
display: none;
|
25
|
+
}
|
26
|
+
|
27
|
+
|
28
|
+
&:hover {
|
29
|
+
.action {
|
30
|
+
visibility: visible;
|
31
|
+
}
|
32
|
+
.d-action-none {
|
33
|
+
display: inherit;
|
34
|
+
}
|
35
|
+
}
|
36
|
+
|
37
|
+
}
|
38
|
+
|
39
|
+
|
40
|
+
|
41
|
+
tr.sticky, thead.sticky {
|
42
|
+
position: sticky;
|
43
|
+
background: white;
|
44
|
+
z-index: 1;
|
45
|
+
}
|
46
|
+
th.sticky-left, td.sticky-left {
|
47
|
+
position: sticky;
|
48
|
+
left: 0px;
|
49
|
+
background: white;
|
50
|
+
}
|
51
|
+
.text-sm {
|
52
|
+
font-size: 11px;
|
53
|
+
}
|
54
|
+
|
55
|
+
.tree-opener {
|
56
|
+
cursor: pointer;
|
57
|
+
.opened {
|
58
|
+
display: none;
|
59
|
+
}
|
60
|
+
&.opened {
|
61
|
+
.opened {
|
62
|
+
display: inline;
|
63
|
+
}
|
64
|
+
.closed {
|
65
|
+
display: none;
|
66
|
+
}
|
67
|
+
}
|
68
|
+
}
|
69
|
+
|
70
|
+
.table-sum {
|
71
|
+
position: fixed;
|
72
|
+
right: 0;
|
73
|
+
bottom: 0;
|
74
|
+
width: 150px;
|
75
|
+
background: white;
|
76
|
+
border: 2px solid black;
|
77
|
+
padding: 2px;
|
78
|
+
text-align: right;
|
79
|
+
margin-right: 5px;
|
80
|
+
z-index: 1000;
|
81
|
+
}
|
82
|
+
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
.widget table.custom-table td {
|
87
|
+
max-width: 120px;
|
88
|
+
overflow: hidden;
|
89
|
+
}
|
@@ -0,0 +1,118 @@
|
|
1
|
+
module CustomTableConcern
|
2
|
+
extend ActiveSupport::Concern
|
3
|
+
|
4
|
+
included do
|
5
|
+
helper CustomTable::ApplicationHelper
|
6
|
+
helper CustomTable::FieldsetHelper
|
7
|
+
helper CustomTable::IconsHelper
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
class_methods do
|
12
|
+
end
|
13
|
+
|
14
|
+
def format_web
|
15
|
+
!(request.format.xlsx? || request.format.csv?)
|
16
|
+
end
|
17
|
+
|
18
|
+
def custom_table collection, variant = nil, default_sorts: "created_at desc", default_search: {}
|
19
|
+
|
20
|
+
@q = collection.ransack(params[:q])
|
21
|
+
@q = collection.ransack((params[:q] || {}).merge(default_search)) if params[:q].nil?
|
22
|
+
|
23
|
+
customization = helpers.custom_table_user_customization_for(collection.model, variant)
|
24
|
+
@q.sorts = customization&.dig(:sorts).presence || default_sorts if @q.sorts.empty?
|
25
|
+
|
26
|
+
collection = @q.result(distinct: true)
|
27
|
+
# collection = collection.page(params[:page]).per(per_page) if format_web && paginate
|
28
|
+
|
29
|
+
if !current_user.nil?
|
30
|
+
current_user.save_custom_table_settings(collection.model, variant, per_page: params[:per]) if !params[:per].nil? && params[:do_not_save_settings].nil?
|
31
|
+
if !params[:q].nil? && !params[:q][:s].nil? && !@q.nil? && !@q.sorts[0].nil? && !@q.sorts[0].name.nil? && params[:do_not_save_settings].nil?
|
32
|
+
current_user.save_custom_table_settings(collection.model, variant, sorts: "#{@q.sorts[0].name} #{@q.sorts[0].dir}")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
return collection
|
37
|
+
end
|
38
|
+
|
39
|
+
def custom_table_export(format, collection, filename: nil)
|
40
|
+
|
41
|
+
filename ||= collection.model.model_name.plural
|
42
|
+
|
43
|
+
format.xlsx do
|
44
|
+
# if collection.count > 1000
|
45
|
+
# redirect_to params.permit!.merge({:format => :html}), alert: t("custom_table.huge_xlsx_alert", csv: helpers.link_to(t("custom_table.download_as_csv"), params.permit!.merge({:format => :csv})))
|
46
|
+
# else
|
47
|
+
response.headers['Content-Disposition'] = "attachment; filename=\"#{filename}.xlsx\""
|
48
|
+
# end
|
49
|
+
end
|
50
|
+
|
51
|
+
format.csv do
|
52
|
+
# Delete this header so that Rack knows to stream the content.
|
53
|
+
headers.delete("Content-Length")
|
54
|
+
# Do not cache results from this action.
|
55
|
+
headers["Cache-Control"] = "no-cache"
|
56
|
+
# Let the browser know that this file is a CSV.
|
57
|
+
headers['Content-Type'] = 'text/csv'
|
58
|
+
# Do not buffer the result when using proxy servers.
|
59
|
+
headers['X-Accel-Buffering'] = 'no'
|
60
|
+
# Set the filename
|
61
|
+
headers['Content-Disposition'] = "attachment; filename=\"#{filename}.csv\""
|
62
|
+
|
63
|
+
global_model_name = collection.model.model_name.singular
|
64
|
+
|
65
|
+
fields = helpers.custom_table_fields_definition_for(collection.model)
|
66
|
+
|
67
|
+
# Allow pre-defined fields for export
|
68
|
+
if !@fields.nil?
|
69
|
+
fields = fields.select { |k, _v| local_assigns[:fields].include?(k) }
|
70
|
+
end
|
71
|
+
|
72
|
+
@csv_enumerator ||= Enumerator.new do |yielder|
|
73
|
+
|
74
|
+
head = []
|
75
|
+
|
76
|
+
fields.each do |field, defs|
|
77
|
+
head.push (defs[:label].nil? ? collection.model.human_attribute_name(field) : defs[:label])
|
78
|
+
end
|
79
|
+
|
80
|
+
yielder << CSV.generate_line(head)
|
81
|
+
|
82
|
+
collection.find_each do |item|
|
83
|
+
|
84
|
+
row = []
|
85
|
+
model_name = item.model_name.singular # Allows to show different class models in one table!
|
86
|
+
|
87
|
+
fields.each do |field, defs|
|
88
|
+
next if defs[:table] == false
|
89
|
+
|
90
|
+
value = helpers.raw_field_value_for(item, field)
|
91
|
+
|
92
|
+
if [Date, ActiveSupport::TimeWithZone].include?(value.class)
|
93
|
+
value = value.to_date
|
94
|
+
end
|
95
|
+
|
96
|
+
row.push value
|
97
|
+
end
|
98
|
+
|
99
|
+
# Extra cols definition
|
100
|
+
if defined?(@extra_cols)
|
101
|
+
row += @extra_cols.call(item)
|
102
|
+
end
|
103
|
+
|
104
|
+
yielder << CSV.generate_line(row)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
self.response_body = @csv_enumerator
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
|
114
|
+
|
115
|
+
private
|
116
|
+
|
117
|
+
|
118
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
module CustomTable
|
2
|
+
class SettingsController < ::ApplicationController
|
3
|
+
|
4
|
+
before_action :authenticate_user!
|
5
|
+
skip_authorization_check # Because we do it manually
|
6
|
+
|
7
|
+
layout false
|
8
|
+
|
9
|
+
def edit
|
10
|
+
@search_model = params[:id].constantize
|
11
|
+
@variant = params[:variant].presence
|
12
|
+
if !@variant.nil? && !helpers.custom_table_variants_for(@search_model).include?(@variant)
|
13
|
+
render status: 404, html: "No such variant: #{@variant}"
|
14
|
+
return
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# PATCH/PUT settings
|
19
|
+
def update
|
20
|
+
|
21
|
+
p = settings_params.to_h
|
22
|
+
|
23
|
+
model = p[:model].constantize
|
24
|
+
variant = p[:variant].presence
|
25
|
+
|
26
|
+
defs = helpers.custom_table_fields_definition_for(model, variant)
|
27
|
+
variants = helpers.custom_table_variants_for(model)
|
28
|
+
|
29
|
+
if !variant.nil? && !variants.include?(variant)
|
30
|
+
render status: 422, html: "No such variant: #{variant}"
|
31
|
+
return
|
32
|
+
end
|
33
|
+
|
34
|
+
if defs.nil?
|
35
|
+
optional_redirect_to profile_path, alert: t("custom_table.customization_not_allowed", model: model)
|
36
|
+
end
|
37
|
+
|
38
|
+
p[:fields].reject!{|k,v| defs[k.to_sym].nil?} # Clearing unknown fields
|
39
|
+
p[:fields].each { |k, v| p[:fields][k] = (defs[k.to_sym][:appear] == :always) ? true : ActiveModel::Type::Boolean.new.cast(v) }
|
40
|
+
|
41
|
+
if current_user.save_custom_table_settings(model, variant, fields: p[:fields])
|
42
|
+
flash[:notice] = t("custom_table.customization_saved")
|
43
|
+
respond_to do |format|
|
44
|
+
format.turbo_stream {render turbo_stream: turbo_stream.action(:refresh, nil)}
|
45
|
+
end
|
46
|
+
else
|
47
|
+
# optional_redirect_to main_app.root_path, alert: t("custom_table.cannot_save_customization")
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
# PATCH/PUT settings
|
53
|
+
def destroy
|
54
|
+
|
55
|
+
model = params[:id].constantize
|
56
|
+
variant = params[:variant].presence
|
57
|
+
|
58
|
+
defs = helpers.custom_table_fields_definition_for(model)
|
59
|
+
variants = helpers.custom_table_variants_for(model)
|
60
|
+
|
61
|
+
if !variant.nil? && !variants.include?(variant)
|
62
|
+
render status: 422, html: "No such variant: #{variant}"
|
63
|
+
return
|
64
|
+
end
|
65
|
+
|
66
|
+
if current_user.destroy_custom_table_settings(model, variant)
|
67
|
+
flash[:notice] = t("custom_table.customization_saved")
|
68
|
+
respond_to do |format|
|
69
|
+
format.turbo_stream {render turbo_stream: turbo_stream.action(:refresh, nil)}
|
70
|
+
end
|
71
|
+
else
|
72
|
+
# optional_redirect_to main_app.root_path, alert: t("custom_table.cannot_save_customization")
|
73
|
+
end
|
74
|
+
|
75
|
+
end
|
76
|
+
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
# Only allow a list of trusted parameters through.
|
81
|
+
def settings_params
|
82
|
+
params.require(:user).permit(:model, :variant, { fields: {} })
|
83
|
+
end
|
84
|
+
|
85
|
+
end
|
86
|
+
end
|