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
data/config/locales/es.yml
CHANGED
data/config/locales/fr.yml
CHANGED
data/config/locales/hu.yml
CHANGED
data/config/locales/ja.yml
CHANGED
data/config/locales/ru.yml
CHANGED
|
@@ -2,22 +2,65 @@ module ActiveScaffold::Actions
|
|
|
2
2
|
module ConfigList
|
|
3
3
|
|
|
4
4
|
def self.included(base)
|
|
5
|
-
base.before_action :
|
|
6
|
-
base.
|
|
5
|
+
base.before_action :set_default_view, :set_default_sorting, :change_view, only: [:index]
|
|
6
|
+
base.before_action :config_list_authorized_filter, only: [:show_config_list, :config_list]
|
|
7
|
+
base.helper_method :config_list_params, :config_list_sorting, :config_list_named_views
|
|
7
8
|
end
|
|
8
9
|
|
|
9
10
|
def show_config_list
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
type.js do
|
|
15
|
-
render(partial: 'show_config_list_form', layout: false)
|
|
16
|
-
end
|
|
11
|
+
config_list_record
|
|
12
|
+
@config_list_view_name = find_view_name(params[:config_list_view])
|
|
13
|
+
if @config_list_view_name.present?
|
|
14
|
+
@global_view = config_list_slug(@config_list_view_name, true) == params[:config_list_view]
|
|
17
15
|
end
|
|
16
|
+
respond_to_action(:show_config_list, config_list_formats)
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def config_list
|
|
20
|
+
do_config_list
|
|
21
|
+
respond_to_action(:config_list, config_list_formats)
|
|
18
22
|
end
|
|
19
23
|
|
|
20
24
|
protected
|
|
25
|
+
|
|
26
|
+
def set_default_view
|
|
27
|
+
return unless params[:config_list_view].nil?
|
|
28
|
+
|
|
29
|
+
default_view = active_scaffold_config.config_list.default_view
|
|
30
|
+
params[:config_list_view] = default_view.to_s if default_view.present?
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def change_view
|
|
34
|
+
active_scaffold_config.list.refresh_with_header = true if params[:config_list_view]
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def config_list_formats
|
|
38
|
+
[:html, :js]
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def show_config_list_respond_to_html
|
|
42
|
+
render(action: 'show_config_list_form', layout: true)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def show_config_list_respond_to_js
|
|
46
|
+
render(partial: 'show_config_list_form', layout: false)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def config_list_respond_to_html
|
|
50
|
+
redirect_to action: :index, config_list_view: params[:config_list_view_name]
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def do_refresh_list
|
|
54
|
+
set_default_sorting
|
|
55
|
+
super
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def config_list_respond_to_js
|
|
59
|
+
do_refresh_list
|
|
60
|
+
active_scaffold_config.list.refresh_with_header = true
|
|
61
|
+
list_url = params_for(action: :index, config_list_view: params[:config_list_view].presence)
|
|
62
|
+
render partial: 'refresh_list', locals: {history_url: url_for(list_url)}, formats: [:js]
|
|
63
|
+
end
|
|
21
64
|
|
|
22
65
|
def set_default_sorting
|
|
23
66
|
if (params['sort_direction'] && params['sort_direction'] == 'reset') || (active_scaffold_config.list.user['sort'].blank? && params['sort'].blank?)
|
|
@@ -25,15 +68,13 @@ module ActiveScaffold::Actions
|
|
|
25
68
|
end
|
|
26
69
|
end
|
|
27
70
|
|
|
28
|
-
def
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
save_config_list_params(config_list, config_list_sorting_params)
|
|
36
|
-
end
|
|
71
|
+
def do_config_list
|
|
72
|
+
config_list = params.delete :config_list
|
|
73
|
+
case config_list
|
|
74
|
+
when String
|
|
75
|
+
delete_config_list_params(params.delete(:config_list_view).presence)
|
|
76
|
+
when Array
|
|
77
|
+
save_config_list_params(config_list, config_list_sorting_params, params.delete(:config_list_view_name).presence, params.delete(:config_list_old_view_name))
|
|
37
78
|
end
|
|
38
79
|
end
|
|
39
80
|
|
|
@@ -70,9 +111,13 @@ module ActiveScaffold::Actions
|
|
|
70
111
|
@active_scaffold_current_user ||= send(self.class.active_scaffold_config.class.security.current_user_method)
|
|
71
112
|
end
|
|
72
113
|
|
|
73
|
-
def delete_config_list_params
|
|
74
|
-
|
|
75
|
-
|
|
114
|
+
def delete_config_list_params(view_name)
|
|
115
|
+
record = config_list_record(view_name)
|
|
116
|
+
if record
|
|
117
|
+
if record.destroy && view_name.present?
|
|
118
|
+
config_list_record(reload: true)
|
|
119
|
+
return
|
|
120
|
+
end
|
|
76
121
|
else
|
|
77
122
|
config_list_session_storage['config_list'] = nil
|
|
78
123
|
config_list_session_storage['config_list_sorting'] = nil
|
|
@@ -82,12 +127,17 @@ module ActiveScaffold::Actions
|
|
|
82
127
|
@config_list_sorting = nil
|
|
83
128
|
end
|
|
84
129
|
|
|
85
|
-
def save_config_list_params(config_list, config_list_sorting)
|
|
86
|
-
if
|
|
87
|
-
|
|
88
|
-
|
|
130
|
+
def save_config_list_params(config_list, config_list_sorting, view_name, old_view_name)
|
|
131
|
+
if view_name.present?
|
|
132
|
+
assign = {view_name: view_name}
|
|
133
|
+
assign[:slug] = config_list_slug(view_name, params.delete(:global_view).present?) if active_scaffold_config.config_list.global_views
|
|
134
|
+
end
|
|
135
|
+
record = config_list_record(old_view_name || assign&.dig(:slug) || view_name, assign: assign)
|
|
136
|
+
|
|
137
|
+
if record
|
|
138
|
+
record.config_list = config_list.select(&:present?).join(',')
|
|
89
139
|
record.config_list_sorting = config_list_sorting if record.respond_to? :config_list_sorting
|
|
90
|
-
record.save
|
|
140
|
+
params[:config_list_view] = assign&.dig(:slug) || view_name if record.save
|
|
91
141
|
else
|
|
92
142
|
config_list_session_storage['config_list'] = config_list.map(&:to_sym)
|
|
93
143
|
config_list_session_storage['config_list_sorting'] = config_list_sorting
|
|
@@ -111,14 +161,52 @@ module ActiveScaffold::Actions
|
|
|
111
161
|
end
|
|
112
162
|
end
|
|
113
163
|
|
|
114
|
-
def config_list_record
|
|
115
|
-
return @config_list_record if defined?
|
|
164
|
+
def config_list_record(view_name = params[:config_list_view], reload: false, assign: nil)
|
|
165
|
+
return @config_list_record if !reload && defined?(@config_list_record)
|
|
116
166
|
@config_list_record =
|
|
117
167
|
if active_scaffold_config.config_list.save_to_user && active_scaffold_current_user
|
|
118
|
-
|
|
168
|
+
if view_name.present?
|
|
169
|
+
options = {attributes: assign}
|
|
170
|
+
options[active_scaffold_config.config_list.global_views ? :slug : :view_name] = view_name
|
|
171
|
+
end
|
|
172
|
+
active_scaffold_current_user.send(
|
|
173
|
+
active_scaffold_config.config_list.save_to_user,
|
|
174
|
+
config_list_session_storage_key,
|
|
175
|
+
config_list_controller_name,
|
|
176
|
+
**options
|
|
177
|
+
)
|
|
119
178
|
end
|
|
120
179
|
end
|
|
121
180
|
|
|
181
|
+
def find_view_name(slug)
|
|
182
|
+
return unless slug.present?
|
|
183
|
+
|
|
184
|
+
config_list_named_views.find do |view_name, view_slug|
|
|
185
|
+
break view_name if slug == (view_slug || view_name)
|
|
186
|
+
end
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
def config_list_slug(view_name, global_view)
|
|
190
|
+
return view_name unless active_scaffold_config.config_list.global_views
|
|
191
|
+
|
|
192
|
+
if ActiveScaffold::Config::ConfigList.slug_builder
|
|
193
|
+
send(ActiveScaffold::Config::ConfigList.slug_builder, view_name, global_view)
|
|
194
|
+
elsif global_view
|
|
195
|
+
"global-#{view_name}"
|
|
196
|
+
else
|
|
197
|
+
"user-#{view_name}"
|
|
198
|
+
end
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def config_list_named_views
|
|
202
|
+
@config_list_named_views ||=
|
|
203
|
+
active_scaffold_current_user.send(
|
|
204
|
+
active_scaffold_config.config_list.named_views_method,
|
|
205
|
+
config_list_session_storage_key,
|
|
206
|
+
config_list_controller_name
|
|
207
|
+
).compact
|
|
208
|
+
end
|
|
209
|
+
|
|
122
210
|
def config_list_params
|
|
123
211
|
unless defined? @config_list_params
|
|
124
212
|
@config_list_params =
|
|
@@ -139,7 +227,9 @@ module ActiveScaffold::Actions
|
|
|
139
227
|
def config_list_sorting
|
|
140
228
|
unless defined? @config_list_sorting
|
|
141
229
|
@config_list_sorting =
|
|
142
|
-
if
|
|
230
|
+
if named_view
|
|
231
|
+
named_view.sorting
|
|
232
|
+
elsif config_list_record
|
|
143
233
|
config_list_record.config_list_sorting if config_list_record.respond_to? :config_list_sorting
|
|
144
234
|
else
|
|
145
235
|
config_list_session_storage['config_list_sorting']
|
|
@@ -149,7 +239,7 @@ module ActiveScaffold::Actions
|
|
|
149
239
|
end
|
|
150
240
|
|
|
151
241
|
def list_columns
|
|
152
|
-
@list_columns ||= begin
|
|
242
|
+
@list_columns ||= named_view_columns || begin
|
|
153
243
|
columns = super
|
|
154
244
|
if config_list_params.present?
|
|
155
245
|
config_list = config_list_params.each.with_index.to_h
|
|
@@ -164,7 +254,24 @@ module ActiveScaffold::Actions
|
|
|
164
254
|
# The default security delegates to ActiveRecordPermissions.
|
|
165
255
|
# You may override the method to customize.
|
|
166
256
|
def config_list_authorized?
|
|
167
|
-
authorized_for?(action: :read)
|
|
257
|
+
named_view.nil? && authorized_for?(action: :read)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
def named_view
|
|
261
|
+
return @named_view unless params[:config_list_view].present?
|
|
262
|
+
|
|
263
|
+
@named_view ||= active_scaffold_config.config_list.named_views.find { |v| v.name == params[:config_list_view] }
|
|
264
|
+
end
|
|
265
|
+
|
|
266
|
+
def named_view_columns
|
|
267
|
+
return unless named_view
|
|
268
|
+
|
|
269
|
+
raise ActiveScaffold::ActionNotAllowed if named_view.security_method && !send(named_view.security_method)
|
|
270
|
+
named_view.columns.visible_columns(flatten: true)
|
|
271
|
+
end
|
|
272
|
+
|
|
273
|
+
def config_list_authorized_filter
|
|
274
|
+
raise ActiveScaffold::ActionNotAllowed unless config_list_authorized?
|
|
168
275
|
end
|
|
169
276
|
end
|
|
170
277
|
end
|
|
@@ -5,7 +5,14 @@ module ActiveScaffold::Config
|
|
|
5
5
|
super
|
|
6
6
|
@link = self.class.link.clone unless self.class.link.nil?
|
|
7
7
|
@save_to_user = self.class.save_to_user
|
|
8
|
+
@named_views_method = self.class.named_views_method
|
|
8
9
|
@draggable = self.class.draggable
|
|
10
|
+
@named_views_position = self.class.named_views_position
|
|
11
|
+
@named_views_selector = self.class.named_views_selector
|
|
12
|
+
@default_view = self.class.default_view
|
|
13
|
+
@unnamed_view_security_method = self.class.unnamed_view_security_method
|
|
14
|
+
@global_views = self.class.global_views
|
|
15
|
+
@named_views = []
|
|
9
16
|
end
|
|
10
17
|
|
|
11
18
|
# global level configuration
|
|
@@ -26,6 +33,35 @@ module ActiveScaffold::Config
|
|
|
26
33
|
# configures the method in user model to save list configuration for every controller
|
|
27
34
|
cattr_accessor :save_to_user
|
|
28
35
|
|
|
36
|
+
# configures the method in user model to return the named views saved for the user,
|
|
37
|
+
# setting it enables saving the views, but requires to set a method in save_to_user
|
|
38
|
+
cattr_accessor :named_views_method
|
|
39
|
+
|
|
40
|
+
# the position to place the named views selector, :left (next to the title),
|
|
41
|
+
# :right or :center (default, before the actions and filters)
|
|
42
|
+
cattr_accessor :named_views_position
|
|
43
|
+
@@named_views_position = :center
|
|
44
|
+
|
|
45
|
+
# the type of selector for named views, :links, :select or :radio
|
|
46
|
+
cattr_accessor :named_views_selector
|
|
47
|
+
@@named_views_selector = :links
|
|
48
|
+
|
|
49
|
+
# named view selected when config_list_view is not present in the request
|
|
50
|
+
cattr_accessor :default_view
|
|
51
|
+
|
|
52
|
+
# method used to check whether the unnamed, configurable list view is available
|
|
53
|
+
cattr_accessor :unnamed_view_security_method
|
|
54
|
+
|
|
55
|
+
# if saving global views is allowed, or named views are always saved for the current user only
|
|
56
|
+
cattr_accessor :global_views
|
|
57
|
+
|
|
58
|
+
# Configures the method to convert a view name to slug, used only when global views are enabled
|
|
59
|
+
# Slugs are needed when global views are enabled, to ensure the name in the params is unique
|
|
60
|
+
# although a user view has the same name as a global view
|
|
61
|
+
# By default is generated with the prefixes global- and user-, but a different method can be setup here
|
|
62
|
+
# so it can be defined in ApplicationController
|
|
63
|
+
cattr_accessor :slug_builder
|
|
64
|
+
|
|
29
65
|
# enable draggable lists to select displayed columns (enabled by default)
|
|
30
66
|
cattr_accessor :draggable
|
|
31
67
|
self.draggable = true
|
|
@@ -44,6 +80,29 @@ module ActiveScaffold::Config
|
|
|
44
80
|
# configures the method in user model to save list configuration for every controller
|
|
45
81
|
attr_accessor :save_to_user
|
|
46
82
|
|
|
83
|
+
# configures the method in user model to return the named views saved for the user,
|
|
84
|
+
# setting it enables saving the views, but requires to set a method in save_to_user
|
|
85
|
+
attr_accessor :named_views_method
|
|
86
|
+
|
|
87
|
+
# the position to place the named views selector, :left (next to the title),
|
|
88
|
+
# :right or :center (default, before the actions and filters)
|
|
89
|
+
attr_accessor :named_views_position
|
|
90
|
+
|
|
91
|
+
# the type of selector for named views, :links, :select or :radio
|
|
92
|
+
attr_accessor :named_views_selector
|
|
93
|
+
|
|
94
|
+
# named view selected when config_list_view is not present in the request
|
|
95
|
+
attr_accessor :default_view
|
|
96
|
+
|
|
97
|
+
# method used to check whether the unnamed, configurable list view is available
|
|
98
|
+
attr_accessor :unnamed_view_security_method
|
|
99
|
+
|
|
100
|
+
# if saving global views is allowed, or named views are always saved for the current user only
|
|
101
|
+
attr_accessor :global_views
|
|
102
|
+
|
|
103
|
+
# generic named views
|
|
104
|
+
attr_reader :named_views
|
|
105
|
+
|
|
47
106
|
# enable draggable lists to select displayed columns
|
|
48
107
|
attr_accessor :draggable
|
|
49
108
|
|
|
@@ -52,12 +111,25 @@ module ActiveScaffold::Config
|
|
|
52
111
|
columns.exclude :created_on, :created_at, :updated_on, :updated_at, :as_marked
|
|
53
112
|
columns.exclude *@core.columns.select{|c| c.association.try(:polymorphic?)}.map(&:name)
|
|
54
113
|
end
|
|
55
|
-
|
|
114
|
+
|
|
56
115
|
# the ActionLink for this action
|
|
57
116
|
attr_accessor :link
|
|
58
117
|
|
|
118
|
+
def add_view(name, columns = nil, &)
|
|
119
|
+
raise ArgumentError, "view '#{name}' already exists" if @named_views.find { |v| v.name == name }
|
|
120
|
+
view = ::ActiveScaffold::DataStructures::NamedView.new(name, self)
|
|
121
|
+
view.columns = columns if columns
|
|
122
|
+
yield view if block_given?
|
|
123
|
+
view.columns ||= [] if view.view
|
|
124
|
+
raise ArgumentError, "no columns defined for view '#{name}'" if view.view.blank? && view.columns.empty?
|
|
125
|
+
|
|
126
|
+
@named_views << view
|
|
127
|
+
view
|
|
128
|
+
end
|
|
129
|
+
|
|
59
130
|
UserSettings.class_eval do
|
|
60
|
-
user_attr :default_columns, :save_to_user, :draggable
|
|
131
|
+
user_attr :default_columns, :save_to_user, :named_views_method, :draggable,
|
|
132
|
+
:named_views_position, :named_views_selector, :default_view, :unnamed_view_security_method, :global_views
|
|
61
133
|
|
|
62
134
|
def label
|
|
63
135
|
@conf.label(core: core)
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveScaffold::DataStructures
|
|
4
|
+
class NamedView
|
|
5
|
+
# the internal name of the view
|
|
6
|
+
attr_reader :name
|
|
7
|
+
|
|
8
|
+
# the label displayed to the user, if it's a symbol will be translated with as_
|
|
9
|
+
attr_writer :label
|
|
10
|
+
|
|
11
|
+
# the method used to check permissions, if returns true, the list view is allowed
|
|
12
|
+
attr_accessor :security_method
|
|
13
|
+
|
|
14
|
+
# the columns in the named view
|
|
15
|
+
attr_reader :columns
|
|
16
|
+
|
|
17
|
+
# default sorting used with this view instead of default
|
|
18
|
+
attr_accessor :sorting
|
|
19
|
+
|
|
20
|
+
# custom partial used to render the list for this view
|
|
21
|
+
attr_accessor :view
|
|
22
|
+
|
|
23
|
+
# additional information displayed as a title in the view selector
|
|
24
|
+
attr_accessor :tooltip
|
|
25
|
+
|
|
26
|
+
def initialize(name, action)
|
|
27
|
+
@name = name.to_s
|
|
28
|
+
@action = action
|
|
29
|
+
@label = name
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
# the label displayed to the user
|
|
33
|
+
def label
|
|
34
|
+
case @label
|
|
35
|
+
when Symbol
|
|
36
|
+
ActiveScaffold::Registry.cache(:translations, @label) { as_(@label) }
|
|
37
|
+
else
|
|
38
|
+
@label
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def columns=(columns)
|
|
43
|
+
@columns = ActionColumns.new(columns).tap { |cols| cols.action = @action }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
@@ -9,6 +9,30 @@ module ActiveScaffold
|
|
|
9
9
|
true
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
+
def ignore_param_for_nested?(key)
|
|
13
|
+
super || key == :config_list_view
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def named_view
|
|
17
|
+
controller.send(:named_view) if active_scaffold_config.actions.include?(:config_list)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def config_list_save_named_views?
|
|
21
|
+
active_scaffold_config.config_list.named_views_method.present?
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def config_list_named_views?
|
|
25
|
+
return unless active_scaffold_config.actions.include? :config_list
|
|
26
|
+
|
|
27
|
+
config_list_save_named_views? || active_scaffold_config.config_list.named_views.present?
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def config_list_global_views?
|
|
31
|
+
return unless active_scaffold_config.actions.include? :config_list
|
|
32
|
+
|
|
33
|
+
config_list_save_named_views? && active_scaffold_config.config_list.global_views
|
|
34
|
+
end
|
|
35
|
+
|
|
12
36
|
def config_list_columns
|
|
13
37
|
columns =
|
|
14
38
|
if config_list_params.is_a?(Array)
|
|
@@ -19,6 +43,70 @@ module ActiveScaffold
|
|
|
19
43
|
end
|
|
20
44
|
columns.map { |c| [column_heading_label(c), c.name] }
|
|
21
45
|
end
|
|
46
|
+
|
|
47
|
+
def user_named_views
|
|
48
|
+
return [] unless config_list_save_named_views?
|
|
49
|
+
config_list_named_views
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def named_views_from_config
|
|
53
|
+
active_scaffold_config.config_list.named_views.filter_map do |view|
|
|
54
|
+
next if view.security_method && !controller.send(view.security_method)
|
|
55
|
+
[view.label, view.name, view.tooltip]
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def config_list_unnamed_view?
|
|
60
|
+
security_method = active_scaffold_config.config_list.unnamed_view_security_method
|
|
61
|
+
security_method.nil? || controller.send(security_method)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def active_scaffold_named_view_selector
|
|
65
|
+
named_views = user_named_views + named_views_from_config
|
|
66
|
+
return unless named_views.any?
|
|
67
|
+
|
|
68
|
+
named_views.unshift [as_(:default_view), ''] if config_list_unnamed_view?
|
|
69
|
+
html = config_list_view_options(named_views, params[:config_list_view].to_s)
|
|
70
|
+
if active_scaffold_config.config_list.named_views_selector == :select
|
|
71
|
+
select_options = as_element_attributes(:config_list_view_select, id: nil)
|
|
72
|
+
html = select_tag('config_list_view', html, select_options)
|
|
73
|
+
end
|
|
74
|
+
html
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def config_list_view_options(named_views, selected)
|
|
78
|
+
case active_scaffold_config.config_list.named_views_selector
|
|
79
|
+
when :links
|
|
80
|
+
url = url_for(params_for(action: :index, config_list_view: '--VIEW--'))
|
|
81
|
+
view = nil
|
|
82
|
+
links = named_views.map do |label, name, tooltip|
|
|
83
|
+
name ||= label
|
|
84
|
+
link_options = as_element_attributes(:config_list_view_link, remote: true, title: tooltip)
|
|
85
|
+
link = link_to(label, url.sub('--VIEW--', ERB::Util.unwrapped_html_escape(name)), link_options)
|
|
86
|
+
view = label if name == selected
|
|
87
|
+
as_element :config_list_view_item, link, class: ('selected' if name == selected)
|
|
88
|
+
end
|
|
89
|
+
as_element(:config_list_view_selected, view || as_(:default_view), class: 'selected-view') +
|
|
90
|
+
as_element(:config_list_views_list, safe_join(links), class: 'views')
|
|
91
|
+
|
|
92
|
+
when :select
|
|
93
|
+
options = named_views.map do |label, name, tooltip|
|
|
94
|
+
option_attributes = as_element_attributes(:config_list_view_option, title: tooltip).to_h.compact
|
|
95
|
+
[label, name || label, option_attributes]
|
|
96
|
+
end
|
|
97
|
+
options_for_select(options, selected)
|
|
98
|
+
|
|
99
|
+
when :radio
|
|
100
|
+
buttons = named_views.map do |label, name, tooltip|
|
|
101
|
+
name ||= label
|
|
102
|
+
radio_options = as_element_attributes(:config_list_view_radio, id: nil)
|
|
103
|
+
as_element(:config_list_view_label, title: tooltip) do
|
|
104
|
+
radio_button_tag('config_list_view', name, name == selected, **radio_options.to_h) + label
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
safe_join(buttons)
|
|
108
|
+
end
|
|
109
|
+
end
|
|
22
110
|
end
|
|
23
111
|
end
|
|
24
|
-
end
|
|
112
|
+
end
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module ActiveScaffoldConfigList
|
|
4
|
+
# app/models/concerns/config_listable.rb
|
|
5
|
+
module ConfigListable
|
|
6
|
+
extend ActiveSupport::Concern
|
|
7
|
+
|
|
8
|
+
class_methods do
|
|
9
|
+
def has_config_lists(model_name,
|
|
10
|
+
association_name: :list_configurations,
|
|
11
|
+
association_options: {},
|
|
12
|
+
view_name_column: :view_name,
|
|
13
|
+
slug_column: :slug,
|
|
14
|
+
controller_column: :controller_id,
|
|
15
|
+
controller_matcher: :controller_name)
|
|
16
|
+
# Define the association
|
|
17
|
+
class_eval do
|
|
18
|
+
has_many association_name, class_name: model_name, **association_options
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
model_class = model_name.to_s.classify.constantize
|
|
22
|
+
view_name_column = nil unless model_class.column_names.include?(view_name_column.to_s)
|
|
23
|
+
slug_column = nil unless model_class.column_names.include?(slug_column.to_s)
|
|
24
|
+
|
|
25
|
+
self.config_list_settings = {
|
|
26
|
+
association_name: association_name,
|
|
27
|
+
model_name: model_name,
|
|
28
|
+
view_name_column: view_name_column,
|
|
29
|
+
slug_column: slug_column,
|
|
30
|
+
controller_column: controller_column,
|
|
31
|
+
model_class: model_class,
|
|
32
|
+
foreign_key: reflect_on_association(association_name).foreign_key,
|
|
33
|
+
controller_matcher: controller_matcher
|
|
34
|
+
}.freeze
|
|
35
|
+
|
|
36
|
+
# Include instance methods
|
|
37
|
+
include ConfigListable::InstanceMethods unless included_modules.include?(ConfigListable::InstanceMethods)
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
included do
|
|
42
|
+
class_attribute :config_list_settings, instance_writer: false, default: nil
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
module InstanceMethods
|
|
46
|
+
def config_list_for(controller_id, controller_name, view_name: nil, slug: nil, attributes: nil)
|
|
47
|
+
settings = self.class.config_list_settings
|
|
48
|
+
query = list_configurations_query(controller_id, controller_name, user_views: slug.nil? || slug.to_s.start_with?('user-'))
|
|
49
|
+
|
|
50
|
+
if slug
|
|
51
|
+
query = query.where(settings[:slug_column] => slug)
|
|
52
|
+
elsif view_name
|
|
53
|
+
query = query.where(settings[:view_name_column] => view_name)
|
|
54
|
+
else
|
|
55
|
+
column = settings[:slug_column] || settings[:view_name_column]
|
|
56
|
+
query = query.where(column => nil) if column
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
query.first_or_initialize.tap do |record|
|
|
60
|
+
record.attributes = map_attribute_names(attributes, settings) if attributes
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def config_list_views(controller_id, controller_name)
|
|
65
|
+
settings = self.class.config_list_settings
|
|
66
|
+
list_configurations_query(controller_id, controller_name)
|
|
67
|
+
.where.not(settings[:view_name_column] => nil)
|
|
68
|
+
.pluck([settings[:view_name_column], settings[:slug_column]].compact)
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def determine_controller_value(controller_id, controller_name, settings)
|
|
74
|
+
matcher = settings[:controller_matcher]
|
|
75
|
+
|
|
76
|
+
case matcher
|
|
77
|
+
when :controller_id
|
|
78
|
+
{settings[:controller_column] => controller_id}
|
|
79
|
+
else
|
|
80
|
+
# Default to controller_id if matcher is a callable
|
|
81
|
+
if matcher.respond_to?(:call)
|
|
82
|
+
matcher.call(controller_id, controller_name)
|
|
83
|
+
else
|
|
84
|
+
# Fallback to controller_name
|
|
85
|
+
{settings[:controller_column] => controller_name}
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def list_configurations_query(controller_id, controller_name, user_views: false)
|
|
91
|
+
settings = self.class.config_list_settings
|
|
92
|
+
query = send(settings[:association_name])
|
|
93
|
+
# Add the OR condition if user_views is false
|
|
94
|
+
query = settings[:model_class].where(settings[:foreign_key] => nil).or(query) unless user_views
|
|
95
|
+
query.where(determine_controller_value(controller_id, controller_name, settings))
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def map_attribute_names(attributes, settings)
|
|
99
|
+
return attributes unless attributes.is_a?(Hash)
|
|
100
|
+
|
|
101
|
+
attributes.symbolize_keys.transform_keys do |key|
|
|
102
|
+
case key
|
|
103
|
+
when :view_name then settings[:view_name_column]
|
|
104
|
+
when :slug then settings[:slug_column]
|
|
105
|
+
else
|
|
106
|
+
key
|
|
107
|
+
end
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
@@ -1,8 +1,10 @@
|
|
|
1
|
+
require 'active_scaffold_config_list/config_listable'
|
|
1
2
|
module ActiveScaffoldConfigList
|
|
2
3
|
class Engine < ::Rails::Engine
|
|
3
4
|
initializer 'active_scaffold_config_list.routes' do
|
|
4
5
|
ActiveSupport.on_load :active_scaffold_routing do
|
|
5
6
|
self::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection][:show_config_list] = :get
|
|
7
|
+
self::ACTIVE_SCAFFOLD_CORE_ROUTING[:collection][:config_list] = :post
|
|
6
8
|
end
|
|
7
9
|
end
|
|
8
10
|
|
|
@@ -11,5 +13,11 @@ module ActiveScaffoldConfigList
|
|
|
11
13
|
ActionView::Base.send :include, ActiveScaffold::Helpers::ConfigListHelpers
|
|
12
14
|
end
|
|
13
15
|
end
|
|
16
|
+
|
|
17
|
+
initializer 'active_scaffold_config_list.active_record' do |app|
|
|
18
|
+
ActiveSupport.on_load :active_record do
|
|
19
|
+
include ActiveScaffoldConfigList::ConfigListable
|
|
20
|
+
end
|
|
21
|
+
end
|
|
14
22
|
end
|
|
15
23
|
end
|