active_scaffold_config_list 3.6.3 → 4.1.0
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/README.md +285 -18
- data/app/assets/javascripts/active_scaffold_config_list.js +41 -0
- data/app/assets/stylesheets/active_scaffold_config_list.scss +66 -0
- data/app/views/active_scaffold_overrides/_list.html.erb +1 -0
- data/app/views/active_scaffold_overrides/_list_header.html.erb +2 -0
- data/app/views/active_scaffold_overrides/_named_views.html.erb +11 -0
- data/app/views/active_scaffold_overrides/_show_config_list_form.html.erb +14 -16
- data/app/views/active_scaffold_overrides/_show_config_list_form_body.html.erb +65 -29
- data/app/views/active_scaffold_overrides/show_config_list_form.html.erb +1 -1
- data/config/locales/de.yml +4 -0
- data/config/locales/en.yml +4 -0
- data/config/locales/es.yml +4 -0
- data/config/locales/fr.yml +4 -0
- data/config/locales/hu.yml +4 -0
- data/config/locales/ja.yml +4 -0
- data/config/locales/ru.yml +4 -0
- data/lib/active_scaffold/actions/config_list.rb +139 -32
- data/lib/active_scaffold/config/config_list.rb +74 -2
- data/lib/active_scaffold/data_structures/named_view.rb +46 -0
- data/lib/active_scaffold/helpers/config_list_helpers.rb +89 -1
- data/lib/active_scaffold_config_list/config_listable.rb +112 -0
- data/lib/active_scaffold_config_list/engine.rb +8 -0
- data/lib/active_scaffold_config_list/version.rb +3 -3
- data/lib/active_scaffold_config_list.rb +18 -1
- metadata +12 -8
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: cd4aa6db1cf82232099715da904d5927b2b8a91d578745e58cdfac14fced1f8e
|
|
4
|
+
data.tar.gz: a789114e4b22710b30eb90df83a544f2861c188013f158e9aa51bb4edd468ee2
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3d8f89d0344fd9cef930a2b670bb5c2c77f42e80d3636b188cb4370cac1319097bc50b91e3cde4581f316b3414b0f04c8832f69dc30183deac8a3c33426a35c0
|
|
7
|
+
data.tar.gz: cc9420929d95e2503b7732816f8cdffaf5adfbb8a43f810fd59735b1c1670da125c20e46f5353de83ca5eb42824be83239144172bd13fa2fb4e51e3dbf4d11c3
|
data/README.md
CHANGED
|
@@ -16,12 +16,13 @@ Overview
|
|
|
16
16
|
========
|
|
17
17
|
|
|
18
18
|
A plugin for Active Scaffold that provides the ability to choose the column to show in the scaffold list at run-time.
|
|
19
|
+
Also, it adds the ability to define named views with other set of columns to choose between the default list view and
|
|
20
|
+
the named views.
|
|
19
21
|
|
|
20
22
|
You have the option of defining a default set of columns for the controller. For example:
|
|
21
23
|
```rb
|
|
22
24
|
config.config_list.default_columns = [:name, :project, :amount]
|
|
23
25
|
```
|
|
24
|
-
If this is not defined then active_scaffold_config.list.columns is used.
|
|
25
26
|
|
|
26
27
|
This is useful when you want the option to look at a potentially large number of columns but be able to
|
|
27
28
|
easily reset back to something that fits on the screen without horizontal scrolling.
|
|
@@ -30,24 +31,127 @@ The available columns in the configure action are the columns defined in `list.c
|
|
|
30
31
|
`config_list.default_columns` is not defined, then it will default to `list.columns`, and the users only will be able
|
|
31
32
|
to remove some columns, they won't be able to add other columns.
|
|
32
33
|
|
|
33
|
-
The configuration data will be saved
|
|
34
|
-
|
|
35
|
-
|
|
34
|
+
The configuration data will be saved in the session.
|
|
35
|
+
|
|
36
|
+
## Named Views
|
|
37
|
+
|
|
38
|
+
It's possible to define named views, with a set of columns, so users can switch between default view and other defined views. Adding a view is done with `add_view` method, and passing a name (symbol or string) and an array of columns:
|
|
36
39
|
|
|
37
40
|
```rb
|
|
38
|
-
conf.config_list.
|
|
41
|
+
conf.config_list.add_view :simple, [:number, :status]
|
|
39
42
|
```
|
|
40
43
|
|
|
41
|
-
|
|
44
|
+
Although it's possible to use a block too, to change other view settings, such as label, sorting, security method and the partial used to render the list. If the label is set, it can be a string, or a symbol to be localized, and the name is used in the URL parameters. When using a block, the columns can be defined in the view instead of the `add_view` call:
|
|
42
45
|
|
|
43
46
|
```rb
|
|
44
|
-
|
|
45
|
-
|
|
47
|
+
conf.config_list.add_view :simple do |view|
|
|
48
|
+
view.label = 'Number and Status'
|
|
49
|
+
view.columns = [:number, :status]
|
|
50
|
+
view.sorting = {number: :desc}
|
|
51
|
+
view.security_method = :simple_view_authorized?
|
|
52
|
+
view.view = 'compact_list'
|
|
53
|
+
end
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
When `view` is set, the named view renders that partial instead of ActiveScaffold's default list partial. The custom partial can use the same assigns and helpers as the normal list.
|
|
57
|
+
|
|
58
|
+
The columns defined in the view are not required to be in the `conf.list.columns`, so it's possible to add views including columns that are not available in the normal config list.
|
|
59
|
+
|
|
60
|
+
Set `tooltip` to add a title to the view in the selector:
|
|
61
|
+
|
|
62
|
+
```rb
|
|
63
|
+
view.tooltip = 'PTO and HR policy'
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The security method is a controller method used to check if the view is available for the user, it must return true when the view is allowed:
|
|
67
|
+
|
|
68
|
+
```rb
|
|
69
|
+
def simple_view_authorized?
|
|
70
|
+
current_user.is_admin?
|
|
46
71
|
end
|
|
47
72
|
```
|
|
48
73
|
|
|
49
|
-
|
|
50
|
-
|
|
74
|
+
When a named view is selected, the configure action link is not rendered.
|
|
75
|
+
|
|
76
|
+
The view selector is displayed in the title header, and it's rendered as a menu of links, displaying the selected view, and the list of available views on hover. The selector can be changed to a list of radio buttons or select field with `conf.config_list.named_views_selector`, per controller, or it can be changed globally in `ActiveScaffold.defaults`:
|
|
77
|
+
|
|
78
|
+
```rb
|
|
79
|
+
conf.config_list.named_views_selector = :radio # use radio buttons
|
|
80
|
+
conf.config_list.named_views_selector = :select # use select field
|
|
81
|
+
conf.config_list.named_views_selector = :links # use a menu of links (default)
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
A named view can be selected by default when the request does not contain `config_list_view`:
|
|
85
|
+
|
|
86
|
+
```rb
|
|
87
|
+
conf.config_list.default_view = 'Calendar'
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
An explicit empty `config_list_view` still selects the ordinary, unnamed list view. For a request-dependent default, set the parameter in a controller callback before ActiveScaffold processes the index action instead of using this static setting.
|
|
91
|
+
|
|
92
|
+
The unnamed choice, shown as "Default" in the selector, is included unless `unnamed_view_security_method` is configured. It is the configurable list that uses saved/session columns or `config_list.default_columns`; it is separate from the named view selected by `default_view`. The method runs on the controller and must return true to include the unnamed choice. This controls selector visibility; applications must still enforce authorization for the underlying list action.
|
|
93
|
+
|
|
94
|
+
```rb
|
|
95
|
+
conf.config_list.unnamed_view_security_method = :unnamed_list_view_authorized?
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
The position of the views selector can be changed with `conf.config_list.named_views_position`, setting it to `:center` (default, between the title and actions), `:left` (next to the title) or `:right` (at the right of the actions). Although the position of the `div.config-list-views` doesn't change, it just adds a class (center, right or left) and use CSS of flexbox layout to change the position (changing `flex-grow` and `order`). It can be changed per controller or globally in `ActiveScaffold.defaults`:
|
|
99
|
+
|
|
100
|
+
```rb
|
|
101
|
+
conf.config_list.named_views_position = :center
|
|
102
|
+
conf.config_list.named_views_position = :left
|
|
103
|
+
conf.config_list.named_views_position = :right
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
The selector and configuration form expose their markup through ActiveScaffold's UI registry. Elements rendered with `as_element` have a default tag that applications may replace with `ActiveScaffold.set_element_tag`. Attribute-only entries are applied to tags produced by Rails helpers such as `form_tag`, `select_tag`, or `radio_button_tag`.
|
|
107
|
+
|
|
108
|
+
Named-view selector elements:
|
|
109
|
+
|
|
110
|
+
| UI element | Rendered control | Purpose |
|
|
111
|
+
| --- | --- | --- |
|
|
112
|
+
| `config_list_views` | `<div>` | Outer container when the selector is `:links`; it receives `config-list-views` and the configured position class. |
|
|
113
|
+
| `config_list_views_form` | `<form>` attributes | Outer form when the selector is `:radio` or `:select`; use it for layout or behavior classes such as `no-autofocus`. |
|
|
114
|
+
| `config_list_view_selected` | `<div>` | Currently selected view displayed by the links selector. |
|
|
115
|
+
| `config_list_views_list` | `<ul>` | Dropdown list containing the links-selector choices. |
|
|
116
|
+
| `config_list_view_item` | `<li>` | One links-selector choice; the current choice also receives `selected`. |
|
|
117
|
+
| `config_list_view_link` | `<a>` attributes | Remote link that selects a view; its `title` contains the named-view tooltip. |
|
|
118
|
+
| `config_list_view_select` | `<select>` attributes | Select control used by the `:select` selector. |
|
|
119
|
+
| `config_list_view_option` | `<option>` attributes | One option in the select selector; its `title` contains the named-view tooltip. |
|
|
120
|
+
| `config_list_view_label` | `<label>` | Label wrapping a radio and its text; its `title` contains the named-view tooltip. |
|
|
121
|
+
| `config_list_view_radio` | `<input type="radio">` attributes | Radio control used by the `:radio` selector. |
|
|
122
|
+
|
|
123
|
+
For example:
|
|
124
|
+
|
|
125
|
+
```rb
|
|
126
|
+
ActiveScaffold.add_element_attributes(:config_list_view_label, class: 'label text-sm')
|
|
127
|
+
ActiveScaffold.add_element_attributes(:config_list_view_radio, class: 'radio radio-xs')
|
|
128
|
+
ActiveScaffold.add_element_attributes(:config_list_view_link, class: 'link')
|
|
129
|
+
ActiveScaffold.add_element_attributes(:config_list_view_select, class: 'select select-sm')
|
|
130
|
+
ActiveScaffold.add_element_attributes(:config_list_views_form, class: 'no-autofocus')
|
|
131
|
+
```
|
|
132
|
+
|
|
133
|
+
Configuration-form elements:
|
|
134
|
+
|
|
135
|
+
| UI element | Rendered control | Purpose |
|
|
136
|
+
| --- | --- | --- |
|
|
137
|
+
| `config_list_columns` | `<ul>` attributes | Checkbox-list container used to select and order visible columns. |
|
|
138
|
+
| `config_list_column` | `<li>` attributes | One entry in the columns checkbox list; it receives `sortable`. |
|
|
139
|
+
| `config_list_sorting` | `<ol>` | Container for the configurable sorting levels. |
|
|
140
|
+
| `config_list_sorting_item` | `<li>` | One sorting level containing its column and direction controls. |
|
|
141
|
+
| `config_list_sorting_column` | `<select>` attributes | Column selector for one sorting level; it receives `column`. |
|
|
142
|
+
| `config_list_sorting_order` | `<select>` attributes | Ascending/descending selector for one sorting level; it receives `order`. |
|
|
143
|
+
| `config_list_view_name` | `<input type="text">` attributes | Name field used to save or rename a view; core ActiveScaffold text-input attributes are also applied. |
|
|
144
|
+
| `config_list_view_rename` | `<label>` | Rename option wrapper; it receives the `rename-view` class required by the JavaScript behavior. |
|
|
145
|
+
| `config_list_view_rename_checkbox` | `<input type="checkbox">` attributes | Checkbox inside the rename option. |
|
|
146
|
+
| `config_list_view_global` | `<label>` | Global-view option wrapper; it receives the `global-view` class required by the JavaScript behavior. |
|
|
147
|
+
| `config_list_view_global_checkbox` | `<input type="checkbox">` attributes | Checkbox choosing whether a saved view is global. |
|
|
148
|
+
|
|
149
|
+
## Saving to DB
|
|
150
|
+
|
|
151
|
+
The configuration data can be saved on the DB. Define a model to store the list configuration, it must have a config_list
|
|
152
|
+
text column storing the columns list, and config_list_sort serialized text column, a foreign key for the user and a column
|
|
153
|
+
saving the controller name or ID. Also, if using saving named views feature, it must have a column to store the view name,
|
|
154
|
+
and a column to store the slug if global views are enabled. For example:
|
|
51
155
|
|
|
52
156
|
```rb
|
|
53
157
|
# == Schema Information
|
|
@@ -61,6 +165,8 @@ serialized text column. For example:
|
|
|
61
165
|
# updated_at :datetime not null
|
|
62
166
|
# controller_id :string(255)
|
|
63
167
|
# user_id :bigint
|
|
168
|
+
# view_name :string
|
|
169
|
+
# slug :string
|
|
64
170
|
#
|
|
65
171
|
# Indexes
|
|
66
172
|
#
|
|
@@ -73,16 +179,125 @@ class ListConfiguration < ApplicationRecord
|
|
|
73
179
|
end
|
|
74
180
|
```
|
|
75
181
|
|
|
76
|
-
Then in
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
182
|
+
Then in your user model call `has_config_lists 'ModelName'` to define the `has_many` association to the model storing
|
|
183
|
+
the list configuration. The method `has_config_lists` requires a model name, and a hash of options:
|
|
184
|
+
|
|
185
|
+
* association_name: defaults to `list_configurations`
|
|
186
|
+
* association_options: the options for the `has_many` association, for example, `dependent`, `as` if the model has a
|
|
187
|
+
polymorphic association because it's used by different user models, foreign_key, and any other option accepted by
|
|
188
|
+
`has_many`.
|
|
189
|
+
* controller_column: the column storing the controller name or ID.
|
|
190
|
+
* controller_matcher: :controller_id, :controller_name, or a proc. If you want to match the controller column with the
|
|
191
|
+
controller name or controller ID (see below for the difference between controller name and ID).
|
|
192
|
+
* view_name_column: the name for the column storing the view name (see Saving Named Views)
|
|
193
|
+
* slug_column: the name of the column storing the slug for the view (see Global Views)
|
|
194
|
+
|
|
195
|
+
```rb
|
|
196
|
+
class User < ApplicationRecord
|
|
197
|
+
has_config_lists 'ListConfiguration', association_options: {dependent: :delete_all}
|
|
198
|
+
end
|
|
199
|
+
```
|
|
200
|
+
|
|
201
|
+
Finally, set the setting `config_list.save_to_user` to `:config_list_for` in the controllers using config_list.
|
|
82
202
|
|
|
83
203
|
```rb
|
|
84
|
-
|
|
85
|
-
|
|
204
|
+
conf.config_list.save_to_user = :config_list_for
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
It can be changed globally for the app in `ActiveScaffold.defaults` in an initializer, such as:
|
|
208
|
+
|
|
209
|
+
```rb
|
|
210
|
+
ActiveScaffold.defaults do |config|
|
|
211
|
+
config.config_list.save_to_user = :config_list_for
|
|
212
|
+
end
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
There are 2 ways to store the list configuration for a controller. Saving the controller name or the controller ID.
|
|
216
|
+
If the user configuration must be shared on different conditions for embedded controllers, and each parent for nested
|
|
217
|
+
controllers, or save unique configurations. The controller ID argument will be different in embedded controllers,
|
|
218
|
+
nested controllers and regular controllers, as it will use `active_scaffold_session_storage_key`, and the controller
|
|
219
|
+
name will always be the same.
|
|
220
|
+
|
|
221
|
+
## Saving Named Views
|
|
222
|
+
|
|
223
|
+
It's possible to save the list configuration with a name, and change between default view, named views defined in the
|
|
224
|
+
config and user named views. Config list will have a field to set the name, when no name is set, it's saved as a normal
|
|
225
|
+
config list, overriding the default view.
|
|
226
|
+
|
|
227
|
+
When a user named view is selected, configure will open the form with that view's settings. If the name is changed, a
|
|
228
|
+
checkbox will show up that allows renaming the current view. Submitting the form without checking that checkbox will
|
|
229
|
+
create a new named view, and will rename the current view if the checkbox is selected. In this case, it isn't possible
|
|
230
|
+
to override the default view, clearing the view's name won't be allowed.
|
|
231
|
+
|
|
232
|
+
Also, when an user named view is selected, the config list form will have a delete link instead of the reset link.
|
|
233
|
+
|
|
234
|
+

|
|
235
|
+
|
|
236
|
+
Enabling this feature requires enabling saving views to the DB, with `conf.config_list.save_to_user`, as it will use
|
|
237
|
+
the same method to get the named view, and set another method in `conf.config_list.named_views_method`. Both options
|
|
238
|
+
can be set per controller, or globally in `ActiveScaffold.defaults`. Set `named_views_method` to `:config_list_views`.
|
|
239
|
+
|
|
240
|
+
## Global Views
|
|
241
|
+
|
|
242
|
+
It's possible to define global views, so they are available to all users. It's enabled with `conf.config_list.global_views`, and requires to use `save_to_user` and `named_views_method` too, as they work as saved named views.
|
|
243
|
+
|
|
244
|
+
When configuring the list, a global view checkbox will show up when the view name is set, but the global checkbox can be
|
|
245
|
+
changed only if a new view is going to be created (the name of the view is changed, and rename is unchecked). Otherwise,
|
|
246
|
+
global view will be disabled, showing if the view is global or not, but can't be changed until the name is edited.
|
|
247
|
+
|
|
248
|
+
The user association in ListConfiguration must be set as optional, as global views will be saved without the user
|
|
249
|
+
foreign key.
|
|
250
|
+
|
|
251
|
+
```rb
|
|
252
|
+
class ListConfiguration < ApplicationRecord
|
|
253
|
+
belongs_to :user, optional: true
|
|
254
|
+
serialize :config_list_sorting, JSON
|
|
255
|
+
end
|
|
256
|
+
```
|
|
257
|
+
|
|
258
|
+
These views require having a name, then when a name is typed, a global view checkbox will show up. It requires another
|
|
259
|
+
column in the list configuration model, `slug`, as there may be a name collision, and it's hard to prevent, because
|
|
260
|
+
it's weird to forbid creating a global view with a name, because some other user already used it for a private view.
|
|
261
|
+
The slug will be built prefixing the view name with `user-` or `global-` by default.
|
|
262
|
+
|
|
263
|
+
If you want to change how slugs are built globally, you can define a method in ApplicationController, and configure it
|
|
264
|
+
with `conf.config_list.slug_builder` in `ActiveScaffold.defaults`. It's a global setting only, can't be set per controller.
|
|
265
|
+
To customize slug builder in a controller, define `config_list_slug` in the controller. The `config_list_slug` method,
|
|
266
|
+
and the slug builder method, will get the view name and global_view boolean, and must return the slug. It's called when
|
|
267
|
+
saving a view. Changing how slugs are generated can break the default `config_list_for` method if the slug for user views
|
|
268
|
+
doesn't start with `user-`.
|
|
269
|
+
|
|
270
|
+
If you want to override a global view with a private view having the same name, so user don't see 2 options with the same
|
|
271
|
+
name in the views selector, override `config_list_views` in your user model, after calling `has_config_lists`, and get
|
|
272
|
+
uniq views by name:
|
|
273
|
+
|
|
274
|
+
```rb
|
|
275
|
+
def config_list_views(*)
|
|
276
|
+
super.uniq { |(name, _)| name }
|
|
277
|
+
end
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
Also, it's possible to override it to change the name of the views, appending an indicator for user views or global views
|
|
281
|
+
when the name is not unique.
|
|
282
|
+
|
|
283
|
+
## Custom model methods
|
|
284
|
+
|
|
285
|
+
It's possible to write custom code in the user model, instead of using `has_config_lists`. Although it's more
|
|
286
|
+
complicated, especially if global views feature is enabled.
|
|
287
|
+
|
|
288
|
+
Define the `has_many` association in the user model, and the method or methods configured in `save_to_user` and
|
|
289
|
+
`named_views_method`.
|
|
290
|
+
|
|
291
|
+
The method configured in `save_to_user` must return the record storing the list configuration for the requested
|
|
292
|
+
controller. The method has 2 arguments, `controller_id` and `controller_name`, so only need to save one of them.
|
|
293
|
+
|
|
294
|
+
```rb
|
|
295
|
+
ActiveScaffold.defaults do |config|
|
|
296
|
+
config.config_list.save_to_user = :config_list_for
|
|
297
|
+
end
|
|
298
|
+
|
|
299
|
+
class User < ApplicationRecord
|
|
300
|
+
has_many :list_configurations, dependent: :delete_all
|
|
86
301
|
def config_list_for(controller_id, controller_name)
|
|
87
302
|
# Use controller_id to allow having different columns on different nested or embedded conditions
|
|
88
303
|
list_configurations.where(controller_id: controller_id).first_or_initialize
|
|
@@ -91,3 +306,55 @@ class User < ActiveRecord::Base
|
|
|
91
306
|
end
|
|
92
307
|
end
|
|
93
308
|
```
|
|
309
|
+
|
|
310
|
+
When `named_views_method` is set, the method in `save_to_user` must accept options with double splat (or keyword
|
|
311
|
+
arguments `view_name` and `attributes`), and it's responsible to look for a named view for the user using view_name,
|
|
312
|
+
and return a new model when none is found. Also, it's responsible to set the view_name from opts[:attributes] (or
|
|
313
|
+
`attributes` keyword arg) in the right column. It can use the same model explained before. When selecting the default
|
|
314
|
+
view, and saving it, the keyword arguments will be nil.
|
|
315
|
+
|
|
316
|
+
```rb
|
|
317
|
+
def config_list_for(controller_id, controller_name, **opts)
|
|
318
|
+
list_configurations.where(controller_id: controller_name, view_name: opts[:view_name]).first_or_initialize.tap do |r|
|
|
319
|
+
r.view_name == opts[:attributes][:view_name] if opts[:attributes]
|
|
320
|
+
end
|
|
321
|
+
end
|
|
322
|
+
```
|
|
323
|
+
|
|
324
|
+
The method in `named_views_method` must return an array with the saved named views for the user, and each item will be an array with the label and name in URL parameter (for example, `view_name` and `slug` columns), or just a string to use for both label and name. This method will receive `controller_id` and `controller_name` arguments, just like the method in `save_to_user`.
|
|
325
|
+
|
|
326
|
+
```rb
|
|
327
|
+
ActiveScaffold.defaults do |config|
|
|
328
|
+
config.config_list.named_views_method = :config_list_views
|
|
329
|
+
end
|
|
330
|
+
|
|
331
|
+
class User < ApplicationRecord
|
|
332
|
+
def config_list_views(controller_id, controller_name)
|
|
333
|
+
list_configurations.where(controller_id: controller_name).where.not(view_name: nil).pluck(:view_name)
|
|
334
|
+
end
|
|
335
|
+
end
|
|
336
|
+
```
|
|
337
|
+
|
|
338
|
+
When using global views, the method configured in `save_to_user` will get another keyword argument, `slug`, instead of `view_name`, and must use this one to find the view. The `attributes` keyword argument will have `slug` key and
|
|
339
|
+
`view_name` key. When the provided slug is for a global view, and no view is found, it shouldn't set the user id, but
|
|
340
|
+
when there is no slug, or the slug is for an user view, the user id should be set:
|
|
341
|
+
|
|
342
|
+
```rb
|
|
343
|
+
def config_list_for(controller_id, controller_name, slug: nil, attributes: nil)
|
|
344
|
+
query = list_configurations
|
|
345
|
+
query = ListConfiguration.where(user_id: nil).or(list_configurations) unless slug.to_s.start_with?('user-')
|
|
346
|
+
query.where(controller_id: controller_name, slug: slug).first_or_initialize.tap do |record|
|
|
347
|
+
record.attributes = attributes if attributes
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
And the method configured in `named_views_method` should return the view name and the slug, so user see the view name, and slug is used in the URL:
|
|
353
|
+
|
|
354
|
+
```rb
|
|
355
|
+
def config_list_views(controller_id, controller_name)
|
|
356
|
+
list_configurations.or(ListConfiguration.where(user_id: nil)).where.not(slug: nil).pluck(:view_name, :slug)
|
|
357
|
+
end
|
|
358
|
+
```
|
|
359
|
+
|
|
360
|
+
It's possible to user other column names than `view_name` and `slug`, just ensure the values are set from `attributes[:view_name]` and `attributes[:slug]`, and use the right column names in the queries.
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
jQuery(document).ready(function () {
|
|
2
|
+
jQuery(document).on('change', '.config-list-views[data-remote]', function () {
|
|
3
|
+
jQuery(this).closest('form').submit();
|
|
4
|
+
});
|
|
5
|
+
jQuery(document).on('ajax:success', '.config-list-views', function () {
|
|
6
|
+
var form = jQuery(this), link = form.parent().find('.actions [data-action="show_config_list"]'),
|
|
7
|
+
href = new URL(link.attr('href'), window.location.origin);
|
|
8
|
+
href.searchParams.set('config_list_view', form.find('select,input[checked]').val());
|
|
9
|
+
link.attr('href', href.toString());
|
|
10
|
+
});
|
|
11
|
+
jQuery(document).on('input', '.show_config_list-view [name="config_list_view_name"]', function () {
|
|
12
|
+
var field = jQuery(this),
|
|
13
|
+
rename = field.parent().find('.rename-view'),
|
|
14
|
+
global = field.parent().find('.global-view'),
|
|
15
|
+
global_hidden = global.find('input[type=hidden]'),
|
|
16
|
+
global_cb = global.find('input[type=checkbox]'),
|
|
17
|
+
rename_cb = rename.find('input[type=checkbox]');
|
|
18
|
+
if (field.val().trim()) global.show();
|
|
19
|
+
else global.hide();
|
|
20
|
+
if (field.val() !== field.attr('value')) {
|
|
21
|
+
rename.show();
|
|
22
|
+
global_hidden.prop('disabled', rename_cb.length ? !rename_cb.prop('checked') : true);
|
|
23
|
+
global_cb.prop('disabled', rename_cb.length ? rename_cb.prop('checked') : false);
|
|
24
|
+
} else {
|
|
25
|
+
rename.hide();
|
|
26
|
+
rename_cb.prop('checked', false);
|
|
27
|
+
global_hidden.prop('disabled', false);
|
|
28
|
+
global_cb.prop('disabled', true);
|
|
29
|
+
global_cb.prop('checked', global_hidden.val() === '1');
|
|
30
|
+
}
|
|
31
|
+
});
|
|
32
|
+
jQuery(document).on('change', '.show_config_list-view .rename-view input[type=checkbox]', function () {
|
|
33
|
+
var rename_cb = jQuery(this),
|
|
34
|
+
global = rename_cb.closest('.form-element').find('.global-view'),
|
|
35
|
+
global_hidden = global.find('input[type=hidden]'),
|
|
36
|
+
global_cb = global.find('input[type=checkbox]');
|
|
37
|
+
global_hidden.prop('disabled', !rename_cb.prop('checked'));
|
|
38
|
+
global_cb.prop('disabled', rename_cb.prop('checked'));
|
|
39
|
+
if (global_cb.prop('disabled')) global_cb.prop('checked', global_hidden.val() === '1');
|
|
40
|
+
});
|
|
41
|
+
});
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
.active-scaffold-header {
|
|
2
|
+
display: flex;
|
|
3
|
+
justify-content: space-between;
|
|
4
|
+
|
|
5
|
+
> .actions {
|
|
6
|
+
order: 1;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
> h2 {
|
|
10
|
+
flex-grow: 1;
|
|
11
|
+
&:has(~ .config-list-views.left) {
|
|
12
|
+
flex-grow: 0;
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
> .config-list-views {
|
|
17
|
+
&.left {
|
|
18
|
+
flex-grow: 1;
|
|
19
|
+
margin-left: 1em;
|
|
20
|
+
}
|
|
21
|
+
&.right {
|
|
22
|
+
order: 2
|
|
23
|
+
}
|
|
24
|
+
display: flex;
|
|
25
|
+
gap: 10px;
|
|
26
|
+
|
|
27
|
+
input[type=radio] {
|
|
28
|
+
margin-right: 5px;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
&:has(.views) {
|
|
32
|
+
position: relative;
|
|
33
|
+
> .selected-view, a {
|
|
34
|
+
display: block;
|
|
35
|
+
padding: 8px 12px;
|
|
36
|
+
white-space: nowrap;
|
|
37
|
+
text-decoration: none;
|
|
38
|
+
color: #333;
|
|
39
|
+
}
|
|
40
|
+
.selected a {
|
|
41
|
+
color: #06c;
|
|
42
|
+
}
|
|
43
|
+
a:hover {
|
|
44
|
+
text-decoration: underline;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
> .views {
|
|
48
|
+
list-style: none;
|
|
49
|
+
padding: 0;
|
|
50
|
+
margin: 0;
|
|
51
|
+
border: 1px solid #ccc;
|
|
52
|
+
display: none;
|
|
53
|
+
background: white;
|
|
54
|
+
}
|
|
55
|
+
&:hover {
|
|
56
|
+
> .views {
|
|
57
|
+
display: block;
|
|
58
|
+
position: absolute;
|
|
59
|
+
top: 0;
|
|
60
|
+
left: 0;
|
|
61
|
+
z-index: 1;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
<%= render named_view&.view || :super %>
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
<% selector_class = "config-list-views #{active_scaffold_config.config_list.named_views_position}" %>
|
|
2
|
+
<% if active_scaffold_config.config_list.named_views_selector == :links %>
|
|
3
|
+
<%= as_element :config_list_views, class: selector_class do %>
|
|
4
|
+
<%= active_scaffold_named_view_selector %>
|
|
5
|
+
<% end %>
|
|
6
|
+
<% else %>
|
|
7
|
+
<% attributes = as_element_attributes(:config_list_views_form, class: selector_class, remote: true, method: :get) %>
|
|
8
|
+
<%= form_tag params_for(action: :index, config_list_view: nil), attributes do %>
|
|
9
|
+
<%= active_scaffold_named_view_selector %>
|
|
10
|
+
<% end %>
|
|
11
|
+
<% end %>
|
|
@@ -1,16 +1,14 @@
|
|
|
1
|
-
<% url_options = params_for(action: :
|
|
2
|
-
<%=
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
</p>
|
|
16
|
-
</form>
|
|
1
|
+
<% url_options = params_for(action: :config_list) -%>
|
|
2
|
+
<%= render partial: 'base_form', locals: {form_action: :config_list,
|
|
3
|
+
method: :post,
|
|
4
|
+
url_options: url_options,
|
|
5
|
+
body_partial: 'show_config_list_form_body',
|
|
6
|
+
multipart: false,
|
|
7
|
+
persistent: false,
|
|
8
|
+
field_descriptions: :show,
|
|
9
|
+
cancel_link: true,
|
|
10
|
+
cancel_text: params[:config_list_view].present? ? :delete : :reset,
|
|
11
|
+
cancel_attrs: {data: {refresh: true, method: :post}},
|
|
12
|
+
cancel_url: url_for(url_options.merge(config_list: '')),
|
|
13
|
+
headline: active_scaffold_config.config_list.label} %>
|
|
14
|
+
|
|
@@ -1,33 +1,69 @@
|
|
|
1
|
-
|
|
1
|
+
<%= as_element :fields_container, class: 'form' do %>
|
|
2
2
|
<% if config_list_columns? %>
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
3
|
+
<%= as_element :form_element, class: 'form-element' do %>
|
|
4
|
+
<%
|
|
5
|
+
columns_options = as_element_attributes(
|
|
6
|
+
:config_list_columns,
|
|
7
|
+
name: 'config_list',
|
|
8
|
+
id: "#{element_form_id(action: :config_list)}-columns",
|
|
9
|
+
class: ('sortable-container' unless active_scaffold_config.config_list.draggable)
|
|
10
|
+
).to_h
|
|
11
|
+
content = active_scaffold_checkbox_list(
|
|
12
|
+
nil,
|
|
13
|
+
config_list_columns,
|
|
14
|
+
config_list_params || config_list_columns.map(&:last),
|
|
15
|
+
columns_options,
|
|
16
|
+
ui_options: {
|
|
17
|
+
draggable_lists: active_scaffold_config.config_list.draggable,
|
|
18
|
+
item_options: as_element_attributes(:config_list_column, class: 'sortable').to_h
|
|
19
|
+
}
|
|
20
|
+
)
|
|
21
|
+
%>
|
|
22
|
+
<%= form_attribute_html(nil, as_(:columns), content, nil, {}) %>
|
|
23
|
+
<% end %>
|
|
16
24
|
<% end %>
|
|
25
|
+
|
|
17
26
|
<% if config_list_sorting? %>
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
<%
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
%>
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
<%= as_element :form_element, class: 'form-element' do %>
|
|
28
|
+
<% content = capture do %>
|
|
29
|
+
<%= as_element :config_list_sorting do %>
|
|
30
|
+
<%
|
|
31
|
+
columns_options = list_columns.select(&:sortable?).map { |c| [c.label, c.name] }
|
|
32
|
+
order_options = ['asc', 'desc'].map { |v| [as_(v), v] }
|
|
33
|
+
selected = config_list_sorting || []
|
|
34
|
+
3.times do |i|
|
|
35
|
+
%>
|
|
36
|
+
<%= as_element :config_list_sorting_item do %>
|
|
37
|
+
<%= select_tag "config_list_sorting[#{i}][]", options_for_select(columns_options, selected: selected[i]&.first), as_element_attributes(:config_list_sorting_column, include_blank: as_(:_select_), class: 'column') %>
|
|
38
|
+
<%= select_tag "config_list_sorting[#{i}][]", options_for_select(order_options, selected: selected[i]&.last), as_element_attributes(:config_list_sorting_order, include_blank: as_(:_select_), class: 'order') %>
|
|
39
|
+
<% end %>
|
|
40
|
+
<% end %>
|
|
41
|
+
<% end %>
|
|
42
|
+
<% end %>
|
|
43
|
+
<%= form_attribute_html(nil, as_(:default_sorting), content, nil, {}) %>
|
|
44
|
+
<% end %>
|
|
32
45
|
<% end %>
|
|
33
|
-
|
|
46
|
+
|
|
47
|
+
<% if config_list_save_named_views? %>
|
|
48
|
+
<%= as_element :form_element, class: 'form-element' do %>
|
|
49
|
+
<% content = capture do %>
|
|
50
|
+
<% name_options = active_scaffold_input_text_options(required: @config_list_view_name.present?) %>
|
|
51
|
+
<%= text_field_tag "config_list_view_name", @config_list_view_name.to_s, as_element_attributes(:config_list_view_name, **name_options) %>
|
|
52
|
+
<% if @config_list_view_name.present? %>
|
|
53
|
+
<%= as_element :config_list_view_rename, class: 'rename-view', style: 'display: none;' do %>
|
|
54
|
+
<%= check_box_tag 'config_list_old_view_name', params[:config_list_view], false, **as_element_attributes(:config_list_view_rename_checkbox, id: nil).to_h %>
|
|
55
|
+
<%= as_ :rename_view, view_name: @config_list_view_name %>
|
|
56
|
+
<% end %>
|
|
57
|
+
<% end %>
|
|
58
|
+
<% if config_list_global_views? %>
|
|
59
|
+
<%= as_element :config_list_view_global, class: 'global-view', style: ('display: none;' if @config_list_view_name.blank?) do %>
|
|
60
|
+
<%= hidden_field_tag 'global_view', @global_view ? '1' : '' %>
|
|
61
|
+
<%= check_box_tag 'global_view', '1', @global_view, **as_element_attributes(:config_list_view_global_checkbox, id: nil, disabled: true).to_h %>
|
|
62
|
+
<%= as_ :global_view %>
|
|
63
|
+
<% end %>
|
|
64
|
+
<% end %>
|
|
65
|
+
<% end %>
|
|
66
|
+
<%= form_attribute_html(nil, as_(:view_name), content, nil, {}) %>
|
|
67
|
+
<% end %>
|
|
68
|
+
<% end %>
|
|
69
|
+
<% end %>
|
data/config/locales/de.yml
CHANGED
data/config/locales/en.yml
CHANGED