plutonium 0.15.3 → 0.15.5
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/plutonium.css +1 -1
- data/app/views/components/sidebar_menu/sidebar_menu_component.rb +1 -1
- data/app/views/components/table_search_input/table_search_input_component.html.erb +3 -3
- data/app/views/resource/_resource_table.html.erb +0 -321
- data/lib/plutonium/core/controllers/authorizable.rb +5 -0
- data/lib/plutonium/core/controllers/entity_scoping.rb +4 -4
- data/lib/plutonium/definition/base.rb +8 -0
- data/lib/plutonium/definition/defineable_props.rb +1 -1
- data/lib/plutonium/definition/presentable.rb +71 -0
- data/lib/plutonium/interaction/README.md +1 -1
- data/lib/plutonium/interaction/base.rb +6 -6
- data/lib/plutonium/lib/deep_freezer.rb +31 -0
- data/lib/plutonium/query/adhoc_block.rb +19 -0
- data/lib/plutonium/query/base.rb +29 -0
- data/lib/plutonium/query/filter.rb +12 -0
- data/lib/plutonium/query/filters/text.rb +77 -0
- data/lib/plutonium/query/model_scope.rb +19 -0
- data/lib/plutonium/resource/controller.rb +14 -7
- data/lib/plutonium/resource/controllers/authorizable.rb +1 -1
- data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +26 -0
- data/lib/plutonium/resource/controllers/crud_actions.rb +2 -5
- data/lib/plutonium/resource/controllers/defineable.rb +0 -2
- data/lib/plutonium/resource/controllers/queryable.rb +36 -20
- data/lib/plutonium/resource/policy.rb +1 -1
- data/lib/plutonium/resource/query_object.rb +61 -147
- data/lib/plutonium/{refinements/parameter_refinements.rb → support/parameters.rb} +5 -7
- data/lib/plutonium/ui/component/methods.rb +1 -1
- data/lib/plutonium/ui/display/resource.rb +19 -15
- data/lib/plutonium/ui/form/query.rb +171 -0
- data/lib/plutonium/ui/form/resource.rb +21 -17
- data/lib/plutonium/ui/table/components/scopes_bar.rb +1 -1
- data/lib/plutonium/ui/table/components/search_bar.rb +6 -139
- data/lib/plutonium/ui/table/resource.rb +10 -9
- data/lib/plutonium/version.rb +1 -1
- data/package-lock.json +2 -2
- data/package.json +1 -1
- metadata +12 -4
- data/lib/plutonium/interaction/concerns/presentable.rb +0 -73
@@ -0,0 +1,77 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Query
|
3
|
+
module Filters
|
4
|
+
class Text < Filter
|
5
|
+
VALID_PREDICATES = [
|
6
|
+
:eq, # Equal
|
7
|
+
:not_eq, # Not equal
|
8
|
+
:matches, # LIKE with wildcards
|
9
|
+
:not_matches, # NOT LIKE with wildcards
|
10
|
+
:starts_with, # LIKE with suffix wildcard
|
11
|
+
:ends_with, # LIKE with prefix wildcard
|
12
|
+
:contains, # LIKE with wildcards on both sides
|
13
|
+
:not_contains # NOT LIKE with wildcards on both sides
|
14
|
+
].freeze
|
15
|
+
|
16
|
+
def initialize(predicate: :eq, **)
|
17
|
+
super(**)
|
18
|
+
unless VALID_PREDICATES.include?(predicate)
|
19
|
+
raise ArgumentError, "unsupported predicate #{predicate}. Valid predicates are: #{VALID_PREDICATES.join(", ")}"
|
20
|
+
end
|
21
|
+
@predicate = predicate
|
22
|
+
end
|
23
|
+
|
24
|
+
def apply(scope, query:)
|
25
|
+
case @predicate
|
26
|
+
when :eq
|
27
|
+
scope.where(key => query)
|
28
|
+
when :not_eq
|
29
|
+
scope.where.not(key => query)
|
30
|
+
when :matches
|
31
|
+
scope.where("#{key} LIKE ?", query.tr("*", "%"))
|
32
|
+
when :not_matches
|
33
|
+
scope.where.not("#{key} LIKE ?", query.tr("*", "%"))
|
34
|
+
when :starts_with
|
35
|
+
scope.where("#{key} LIKE ?", "#{sanitize_like(query)}%")
|
36
|
+
when :ends_with
|
37
|
+
scope.where("#{key} LIKE ?", "%#{sanitize_like(query)}")
|
38
|
+
when :contains
|
39
|
+
scope.where("#{key} LIKE ?", "%#{sanitize_like(query)}%")
|
40
|
+
when :not_contains
|
41
|
+
scope.where.not("#{key} LIKE ?", "%#{sanitize_like(query)}%")
|
42
|
+
else
|
43
|
+
raise NotImplementedError, "text filter predicate #{@predicate}"
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def customize_inputs
|
48
|
+
input :query
|
49
|
+
field :query, placeholder: generate_placeholder
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def generate_placeholder
|
55
|
+
base = key.to_s.humanize
|
56
|
+
case @predicate
|
57
|
+
when :matches, :not_matches
|
58
|
+
"#{base} (use * as wildcard)"
|
59
|
+
when :starts_with
|
60
|
+
"#{base} starts with..."
|
61
|
+
when :ends_with
|
62
|
+
"#{base} ends with..."
|
63
|
+
when :contains, :not_contains
|
64
|
+
"#{base} contains..."
|
65
|
+
else
|
66
|
+
base
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def sanitize_like(string)
|
71
|
+
# Escape special LIKE characters: %, _, and \
|
72
|
+
string.gsub(/[%_\\]/) { |char| "\\#{char}" }
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Query
|
3
|
+
class ModelScope < Base
|
4
|
+
attr_reader :name
|
5
|
+
|
6
|
+
# Initializes a ModelScope with a given name.
|
7
|
+
#
|
8
|
+
# @param name [Symbol] The name of the scope.
|
9
|
+
def initialize(name)
|
10
|
+
super()
|
11
|
+
@name = name
|
12
|
+
end
|
13
|
+
|
14
|
+
def apply(scope, **)
|
15
|
+
scope.public_send(name, **)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -1,9 +1,6 @@
|
|
1
1
|
require "action_controller"
|
2
2
|
require "pagy"
|
3
3
|
|
4
|
-
require File.expand_path("refinements/parameter_refinements", Plutonium.lib_root)
|
5
|
-
using Plutonium::Refinements::ParameterRefinements
|
6
|
-
|
7
4
|
module Plutonium
|
8
5
|
module Resource
|
9
6
|
# Controller module to handle resource actions and concerns
|
@@ -172,8 +169,13 @@ module Plutonium
|
|
172
169
|
# @param [Hash] input_params The input parameters
|
173
170
|
def override_entity_scoping_params(input_params)
|
174
171
|
if scoped_to_entity?
|
175
|
-
input_params
|
176
|
-
|
172
|
+
if input_params.key?(scoped_entity_param_key) || resource_class.method_defined?(:"#{scoped_entity_param_key}=")
|
173
|
+
input_params[scoped_entity_param_key] = current_scoped_entity
|
174
|
+
end
|
175
|
+
|
176
|
+
if input_params.key?(:"#{scoped_entity_param_key}_id") || resource_class.method_defined?(:"#{scoped_entity_param_key}_id=")
|
177
|
+
input_params[:"#{scoped_entity_param_key}_id"] = current_scoped_entity.id
|
178
|
+
end
|
177
179
|
end
|
178
180
|
end
|
179
181
|
|
@@ -181,8 +183,13 @@ module Plutonium
|
|
181
183
|
# @param [Hash] input_params The input parameters
|
182
184
|
def override_parent_params(input_params)
|
183
185
|
if current_parent.present?
|
184
|
-
input_params
|
185
|
-
|
186
|
+
if input_params.key?(parent_input_param) || resource_class.method_defined?(:"#{parent_input_param}=")
|
187
|
+
input_params[parent_input_param] = current_parent
|
188
|
+
end
|
189
|
+
|
190
|
+
if input_params.key?(:"#{parent_input_param}_id") || resource_class.method_defined?(:"#{parent_input_param}_id=")
|
191
|
+
input_params[:"#{parent_input_param}_id"] = current_parent.id
|
192
|
+
end
|
186
193
|
end
|
187
194
|
end
|
188
195
|
|
@@ -77,7 +77,7 @@ module Plutonium
|
|
77
77
|
#
|
78
78
|
# @raise [ActionMissingCurrentAuthorizedScope] if current_authorized_scope hasn't been called
|
79
79
|
def verify_current_authorized_scope
|
80
|
-
return if
|
80
|
+
return if verify_current_authorized_scope_skipped
|
81
81
|
return if current_authorized_scope_count > 0
|
82
82
|
|
83
83
|
raise ActionMissingCurrentAuthorizedScope.new(controller_path, action_name)
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Resource
|
3
|
+
module Controllers
|
4
|
+
module CrudActions
|
5
|
+
module IndexAction
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def setup_index_action!
|
11
|
+
@pagy, @resource_records = pagy filtered_resource_collection
|
12
|
+
end
|
13
|
+
|
14
|
+
def filtered_resource_collection
|
15
|
+
query_params = current_definition
|
16
|
+
.query_form.new(nil, query_object: current_query_object, page_size: nil)
|
17
|
+
.extract_input(params)[:q]
|
18
|
+
|
19
|
+
base_query = current_authorized_scope
|
20
|
+
current_query_object.apply(base_query, query_params)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -3,6 +3,7 @@ module Plutonium
|
|
3
3
|
module Controllers
|
4
4
|
module CrudActions
|
5
5
|
extend ActiveSupport::Concern
|
6
|
+
include IndexAction
|
6
7
|
|
7
8
|
included do
|
8
9
|
helper_method :preferred_action_after_submit
|
@@ -13,11 +14,7 @@ module Plutonium
|
|
13
14
|
authorize_current! resource_class
|
14
15
|
set_page_title resource_class.model_name.human.pluralize.titleize
|
15
16
|
|
16
|
-
|
17
|
-
base_query = current_authorized_scope
|
18
|
-
base_query = @search_object.apply(base_query)
|
19
|
-
# base_query = base_query.public_send(params[:scope].to_sym) if params[:scope].present?
|
20
|
-
@pagy, @resource_records = pagy base_query
|
17
|
+
setup_index_action!
|
21
18
|
|
22
19
|
render :index
|
23
20
|
end
|
@@ -1,5 +1,3 @@
|
|
1
|
-
using Plutonium::Refinements::ParameterRefinements
|
2
|
-
|
3
1
|
module Plutonium
|
4
2
|
module Resource
|
5
3
|
module Controllers
|
@@ -7,7 +5,7 @@ module Plutonium
|
|
7
5
|
extend ActiveSupport::Concern
|
8
6
|
|
9
7
|
included do
|
10
|
-
helper_method :
|
8
|
+
helper_method :raw_resource_query_params, :current_query_object
|
11
9
|
end
|
12
10
|
|
13
11
|
def resource_query_object(resource_class, params)
|
@@ -16,28 +14,46 @@ module Plutonium
|
|
16
14
|
end
|
17
15
|
|
18
16
|
def current_query_object
|
19
|
-
@current_query_object ||=
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
17
|
+
@current_query_object ||=
|
18
|
+
Plutonium::Resource::QueryObject.new(resource_class, raw_resource_query_params) do |query_object|
|
19
|
+
if current_definition.search_definition
|
20
|
+
query_object.define_search proc { |scope, search:|
|
21
|
+
current_definition.search_definition.call(scope, search)
|
22
|
+
}
|
23
|
+
end
|
24
|
+
|
25
|
+
current_definition.defined_scopes.each do |key, value|
|
26
|
+
query_object.define_scope key, value[:block], **value[:options]
|
27
|
+
end
|
28
|
+
|
29
|
+
current_definition.defined_sorts.each do |key, value|
|
30
|
+
query_object.define_sorter key, value[:block], **value[:options]
|
31
|
+
end
|
32
|
+
|
33
|
+
current_definition.defined_filters.each do |key, value|
|
34
|
+
with = value[:options][:with]
|
35
|
+
if with.is_a?(Class) && with < Plutonium::Query::Filter
|
36
|
+
options = value[:options].except(:with)
|
37
|
+
options[:key] ||= key
|
38
|
+
with = with.new(**options)
|
39
|
+
end
|
40
|
+
query_object.define_filter key, with, &value[:block]
|
41
|
+
end
|
42
|
+
|
43
|
+
query_object
|
28
44
|
end
|
45
|
+
end
|
29
46
|
|
30
|
-
|
31
|
-
|
47
|
+
def raw_resource_query_params
|
48
|
+
@raw_resource_query_params ||= begin
|
49
|
+
query_params = params[:q]
|
50
|
+
if query_params.is_a?(ActionController::Parameters)
|
51
|
+
query_params.to_unsafe_h
|
52
|
+
else
|
53
|
+
{}.with_indifferent_access
|
32
54
|
end
|
33
|
-
|
34
|
-
query_object
|
35
55
|
end
|
36
56
|
end
|
37
|
-
|
38
|
-
def resource_query_params
|
39
|
-
(params[:q]&.nilify&.to_unsafe_h || {}).with_indifferent_access
|
40
|
-
end
|
41
57
|
end
|
42
58
|
end
|
43
59
|
end
|
@@ -1,127 +1,27 @@
|
|
1
1
|
module Plutonium
|
2
2
|
module Resource
|
3
3
|
class QueryObject
|
4
|
-
class << self
|
5
|
-
end
|
6
|
-
|
7
|
-
class Query
|
8
|
-
include Plutonium::Core::Definers::FieldInputDefiner
|
9
|
-
|
10
|
-
# Applies the query to the given scope using the provided parameters.
|
11
|
-
#
|
12
|
-
# @param scope [Object] The initial scope to which the query will be applied.
|
13
|
-
# @param params [Hash] The parameters for the query.
|
14
|
-
# @return [Object] The modified scope.
|
15
|
-
def apply(scope, params)
|
16
|
-
params = extract_query_params(params)
|
17
|
-
|
18
|
-
if input_definitions.size == params.size
|
19
|
-
apply_internal(scope, params)
|
20
|
-
else
|
21
|
-
scope
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
# Abstract method to apply the query logic to the scope.
|
28
|
-
# Should be implemented by subclasses.
|
29
|
-
#
|
30
|
-
# @param scope [Object] The initial scope.
|
31
|
-
# @param params [Hash] The parameters for the query.
|
32
|
-
# @raise [NotImplementedError] If the method is not implemented.
|
33
|
-
def apply_internal(scope, params)
|
34
|
-
raise NotImplementedError, "#{self.class}#apply_internal"
|
35
|
-
end
|
36
|
-
|
37
|
-
# Extracts query parameters based on the defined inputs.
|
38
|
-
#
|
39
|
-
# @param params [Hash] The parameters to extract.
|
40
|
-
# @return [Hash] The extracted and symbolized parameters.
|
41
|
-
def extract_query_params(params)
|
42
|
-
input_definitions.collect_all(params).compact.symbolize_keys
|
43
|
-
end
|
44
|
-
|
45
|
-
# @return [nil] The resource class (default implementation returns nil).
|
46
|
-
def resource_class = nil
|
47
|
-
end
|
48
|
-
|
49
|
-
class ScopeQuery < Query
|
50
|
-
attr_reader :name
|
51
|
-
|
52
|
-
# Initializes a ScopeQuery with a given name.
|
53
|
-
#
|
54
|
-
# @param name [Symbol] The name of the scope.
|
55
|
-
def initialize(name)
|
56
|
-
@name = name
|
57
|
-
yield self if block_given?
|
58
|
-
end
|
59
|
-
|
60
|
-
private
|
61
|
-
|
62
|
-
# Applies the scope query to the given scope.
|
63
|
-
#
|
64
|
-
# @param scope [Object] The initial scope.
|
65
|
-
# @param params [Hash] The parameters for the query.
|
66
|
-
# @return [Object] The modified scope.
|
67
|
-
def apply_internal(scope, params)
|
68
|
-
scope.public_send(name, **params)
|
69
|
-
end
|
70
|
-
end
|
71
|
-
|
72
|
-
class BlockQuery < Query
|
73
|
-
attr_reader :body
|
74
|
-
|
75
|
-
# Initializes a BlockQuery with a given block of code.
|
76
|
-
#
|
77
|
-
# @param body [Proc] The block of code for the query.
|
78
|
-
def initialize(body)
|
79
|
-
@body = body
|
80
|
-
yield self if block_given?
|
81
|
-
end
|
82
|
-
|
83
|
-
private
|
84
|
-
|
85
|
-
# Applies the block query to the given scope.
|
86
|
-
#
|
87
|
-
# @param scope [Object] The initial scope.
|
88
|
-
# @param params [Hash] The parameters for the query.
|
89
|
-
# @return [Object] The modified scope.
|
90
|
-
def apply_internal(scope, params)
|
91
|
-
if body.arity == 1
|
92
|
-
body.call(scope)
|
93
|
-
else
|
94
|
-
body.call(scope, **params)
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
98
|
-
|
99
4
|
attr_reader :search_filter, :search_query
|
100
5
|
|
101
|
-
# Initializes a QueryObject with the given
|
6
|
+
# Initializes a QueryObject with the given resource_class and parameters.
|
102
7
|
#
|
103
|
-
# @param
|
8
|
+
# @param resource_class [Object] The resource class.
|
104
9
|
# @param params [Hash] The parameters for initialization.
|
105
|
-
def initialize(
|
106
|
-
@
|
10
|
+
def initialize(resource_class, params, &)
|
11
|
+
@resource_class = resource_class
|
12
|
+
@params = params
|
107
13
|
|
108
14
|
define_standard_queries
|
109
|
-
define_scopes
|
110
|
-
define_filters
|
111
|
-
define_sorters
|
112
|
-
|
113
15
|
yield self if block_given?
|
114
|
-
|
115
|
-
|
116
|
-
extract_sort_params(params)
|
16
|
+
extract_filter_params
|
17
|
+
extract_sort_params
|
117
18
|
end
|
118
19
|
|
119
20
|
# Defines a filter with the given name and body.
|
120
21
|
#
|
121
22
|
# @param name [Symbol] The name of the filter.
|
122
23
|
# @param body [Proc, nil] The body of the filter.
|
123
|
-
def define_filter(name, body
|
124
|
-
body ||= name
|
24
|
+
def define_filter(name, body, &)
|
125
25
|
filter_definitions[name] = build_query(body, &)
|
126
26
|
end
|
127
27
|
|
@@ -145,7 +45,7 @@ module Plutonium
|
|
145
45
|
end
|
146
46
|
|
147
47
|
sort_definitions[name] = build_query(body) do |query|
|
148
|
-
query.
|
48
|
+
query.input :direction
|
149
49
|
end
|
150
50
|
end
|
151
51
|
|
@@ -154,7 +54,7 @@ module Plutonium
|
|
154
54
|
# @param body [Proc, Symbol] The body of the search filter.
|
155
55
|
def define_search(body)
|
156
56
|
@search_filter = build_query(body) do |query|
|
157
|
-
query.
|
57
|
+
query.input :search
|
158
58
|
end
|
159
59
|
end
|
160
60
|
|
@@ -172,17 +72,21 @@ module Plutonium
|
|
172
72
|
q[:sort_fields] = selected_sort_fields.dup
|
173
73
|
handle_sort_options!(q, options)
|
174
74
|
|
175
|
-
|
75
|
+
q.merge! params.slice(*filter_definitions.keys)
|
76
|
+
query_params = deep_compact({q: q}).to_param
|
77
|
+
"?#{query_params}"
|
176
78
|
end
|
177
79
|
|
178
80
|
# Applies the defined filters and sorts to the given scope.
|
179
81
|
#
|
180
82
|
# @param scope [Object] The initial scope to which filters and sorts are applied.
|
181
83
|
# @return [Object] The modified scope.
|
182
|
-
def apply(scope)
|
183
|
-
|
184
|
-
scope =
|
185
|
-
|
84
|
+
def apply(scope, params)
|
85
|
+
params = deep_compact(params.with_indifferent_access)
|
86
|
+
scope = search_filter.apply(scope, search: params[:search]) if search_filter && params[:search]
|
87
|
+
scope = scope_definitions[params[:scope]].apply(scope, **{}) if scope_definitions[params[:scope]]
|
88
|
+
scope = apply_sorts(scope, params)
|
89
|
+
apply_filters(scope, params)
|
186
90
|
end
|
187
91
|
|
188
92
|
def scope_definitions = @scope_definitions ||= {}.with_indifferent_access
|
@@ -208,22 +112,7 @@ module Plutonium
|
|
208
112
|
|
209
113
|
private
|
210
114
|
|
211
|
-
attr_reader :
|
212
|
-
|
213
|
-
# Defines standard filters.
|
214
|
-
def define_filters
|
215
|
-
# Implement filter definitions if needed
|
216
|
-
end
|
217
|
-
|
218
|
-
# Defines standard scopes.
|
219
|
-
def define_scopes
|
220
|
-
# Implement scope definitions if needed
|
221
|
-
end
|
222
|
-
|
223
|
-
# Defines standard sorters.
|
224
|
-
def define_sorters
|
225
|
-
# Implement sorter definitions if needed
|
226
|
-
end
|
115
|
+
attr_reader :resource_class, :params, :selected_sort_fields, :selected_sort_directions, :selected_scope_filter
|
227
116
|
|
228
117
|
# Defines standard queries for search and scope.
|
229
118
|
def define_standard_queries
|
@@ -233,7 +122,7 @@ module Plutonium
|
|
233
122
|
# Extracts filter parameters from the given params.
|
234
123
|
#
|
235
124
|
# @param params [Hash] The parameters to extract.
|
236
|
-
def extract_filter_params
|
125
|
+
def extract_filter_params
|
237
126
|
@search_query = params[:search]
|
238
127
|
@selected_scope_filter = params[:scope]
|
239
128
|
end
|
@@ -241,7 +130,7 @@ module Plutonium
|
|
241
130
|
# Extracts sort parameters from the given params.
|
242
131
|
#
|
243
132
|
# @param params [Hash] The parameters to extract.
|
244
|
-
def extract_sort_params
|
133
|
+
def extract_sort_params
|
245
134
|
@selected_sort_fields = Array(params[:sort_fields])
|
246
135
|
@selected_sort_fields &= sort_definitions.keys
|
247
136
|
|
@@ -251,17 +140,24 @@ module Plutonium
|
|
251
140
|
# Builds a query object based on the given body and optional block.
|
252
141
|
#
|
253
142
|
# @param body [Proc, Symbol] The body of the query.
|
254
|
-
# @yieldparam query [Query] The query object.
|
255
|
-
# @return [Query] The constructed query object.
|
256
|
-
def build_query(body
|
257
|
-
case body
|
143
|
+
# @yieldparam query [Plutonium::Query::Base] The query object.
|
144
|
+
# @return [Plutonium::Query::Base] The constructed query object.
|
145
|
+
def build_query(body)
|
146
|
+
query = case body
|
258
147
|
when Symbol
|
259
148
|
raise "Cannot find scope :#{body} on #{resource_class}" unless resource_class.respond_to?(body)
|
260
149
|
|
261
|
-
|
150
|
+
Plutonium::Query::ModelScope.new(body)
|
151
|
+
when Proc
|
152
|
+
Plutonium::Query::AdhocBlock.new(body)
|
153
|
+
when Plutonium::Query::Filter
|
154
|
+
body
|
262
155
|
else
|
263
|
-
|
156
|
+
raise NotImplementedError, "Unsupported query body: #{body.class} -> #{body}"
|
264
157
|
end
|
158
|
+
|
159
|
+
yield query if block_given?
|
160
|
+
query
|
265
161
|
end
|
266
162
|
|
267
163
|
# Determines the sort field for the given name.
|
@@ -284,7 +180,7 @@ module Plutonium
|
|
284
180
|
# @param params [Hash] The parameters to extract.
|
285
181
|
# @return [Hash] The extracted sort directions.
|
286
182
|
def extract_sort_directions(params)
|
287
|
-
params[:sort_directions]&.slice(*sort_definitions.keys) || {}
|
183
|
+
params[:sort_directions]&.slice(*sort_definitions.keys.map(&:to_sym)) || {}
|
288
184
|
end
|
289
185
|
|
290
186
|
# Handles the sort options for building the URL.
|
@@ -322,19 +218,37 @@ module Plutonium
|
|
322
218
|
#
|
323
219
|
# @param scope [Object] The initial scope.
|
324
220
|
# @return [Object] The modified scope.
|
325
|
-
def apply_sorts(scope)
|
221
|
+
def apply_sorts(scope, params)
|
222
|
+
selected_sort_directions = extract_sort_directions(params)
|
326
223
|
selected_sort_fields.each do |name|
|
327
|
-
sorter = sort_definitions[name]
|
328
|
-
|
224
|
+
next unless (sorter = sort_definitions[name])
|
225
|
+
|
226
|
+
direction = selected_sort_directions[name] || "ASC"
|
227
|
+
scope = sorter.apply(scope, direction:)
|
228
|
+
end
|
229
|
+
scope
|
230
|
+
end
|
231
|
+
|
232
|
+
def apply_filters(scope, params)
|
233
|
+
filter_definitions.each do |name, filter|
|
234
|
+
name = name.to_sym
|
235
|
+
filter_params = params[name]
|
236
|
+
next if filter_params.blank?
|
329
237
|
|
330
|
-
|
331
|
-
scope = sorter.apply(scope, params)
|
238
|
+
scope = filter.apply(scope, **filter_params.symbolize_keys)
|
332
239
|
end
|
333
240
|
scope
|
334
241
|
end
|
335
242
|
|
336
|
-
|
337
|
-
|
243
|
+
def deep_compact(hash)
|
244
|
+
hash.transform_values do |value|
|
245
|
+
if value.respond_to?(:transform_values)
|
246
|
+
deep_compact(value).presence
|
247
|
+
else
|
248
|
+
value.presence
|
249
|
+
end
|
250
|
+
end.compact
|
251
|
+
end
|
338
252
|
end
|
339
253
|
end
|
340
254
|
end
|
@@ -1,11 +1,9 @@
|
|
1
|
-
require "action_controller"
|
2
|
-
|
3
1
|
module Plutonium
|
4
|
-
module
|
5
|
-
module
|
6
|
-
|
7
|
-
def nilify
|
8
|
-
transform_values { |value| nilify_internal
|
2
|
+
module Support
|
3
|
+
module Parameters
|
4
|
+
class << self
|
5
|
+
def nilify(params)
|
6
|
+
params.transform_values { |value| nilify_internal(value) }
|
9
7
|
end
|
10
8
|
|
11
9
|
private
|
@@ -37,27 +37,31 @@ module Plutonium
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def render_resource_field(name)
|
40
|
-
# display :name, as: :string
|
41
|
-
# display :description, class: "col-span-full"
|
42
|
-
# display :age, field: {class: "max-h-fit"}
|
43
|
-
# display :dob do |f|
|
44
|
-
# f.date_tag
|
45
|
-
# end
|
46
|
-
|
47
40
|
when_permitted(name) do
|
41
|
+
# field :name, as: :string
|
42
|
+
# display :name, as: :string
|
43
|
+
# display :description, class: "col-span-full"
|
44
|
+
# display :age, tag: {class: "max-h-fit"}
|
45
|
+
# display :dob do |f|
|
46
|
+
# f.date_tag
|
47
|
+
# end
|
48
|
+
|
49
|
+
field_options = resource_definition.defined_fields[name] ? resource_definition.defined_fields[name][:options] : {}
|
50
|
+
|
48
51
|
display_definition = resource_definition.defined_displays[name] || {}
|
49
52
|
display_options = display_definition[:options] || {}
|
50
|
-
display_field_as = display_options.delete(:as)
|
51
53
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
f.
|
54
|
+
tag = field_options[:as] || display_options[:as]
|
55
|
+
tag_attributes = display_options[:tag] || {}
|
56
|
+
tag_block = display_definition[:block] || ->(f) {
|
57
|
+
tag ||= f.inferred_field_component
|
58
|
+
f.send(:"#{tag}_tag", **tag_attributes)
|
56
59
|
}
|
57
60
|
|
58
|
-
field_options =
|
59
|
-
|
60
|
-
|
61
|
+
field_options = field_options.except(:as)
|
62
|
+
wrapper_options = display_options.except(:tag, :as)
|
63
|
+
render field(name, **field_options).wrapped(**wrapper_options) do |f|
|
64
|
+
render tag_block.call(f)
|
61
65
|
end
|
62
66
|
end
|
63
67
|
end
|