plutonium 0.10.2 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -0
- data/Rakefile +1 -2
- data/app/assets/application.js.bk +31419 -0
- data/app/assets/plutonium-logo-original.png +0 -0
- data/app/assets/plutonium-logo-white.png +0 -0
- data/app/assets/plutonium-logo.png +0 -0
- data/app/assets/plutonium.css +1 -0
- data/app/assets/plutonium.ico +0 -0
- data/app/assets/plutonium.js +12416 -0
- data/app/assets/plutonium.js.map +7 -0
- data/app/assets/plutonium.min.js +39 -0
- data/app/assets/plutonium.min.js.map +7 -0
- data/app/views/application/_flash_alerts.html.erb +5 -2
- data/app/views/application/_flash_toasts.html.erb +2 -0
- data/app/views/application/_resource_header.html.erb +263 -697
- data/app/views/application/_resource_sidebar.html.erb +14 -12
- data/app/views/components/action_button/action_button_component.rb +3 -3
- data/app/views/components/attributes.rb +184 -0
- data/app/views/components/base.rb +19 -40
- data/app/views/components/block/block_component.html.erb +1 -1
- data/app/views/components/block/block_component.rb +11 -7
- data/app/views/components/breadcrumbs/breadcrumbs_component.rb +3 -3
- data/app/views/components/button/button_component.html.erb +2 -2
- data/app/views/components/button/button_component.rb +10 -5
- data/app/views/components/dyna_frame_content/dyna_frame_content_component.html.erb +1 -0
- data/app/views/components/dyna_frame_content/dyna_frame_content_component.rb +3 -3
- data/app/views/components/dyna_frame_host/dyna_frame_host_component.html.erb +1 -2
- data/app/views/components/dyna_frame_host/dyna_frame_host_component.rb +12 -5
- data/app/views/components/empty_card/empty_card_component.rb +3 -3
- data/app/views/components/form/form_builder.rb +1 -1
- data/app/views/components/form/form_component.rb +3 -3
- data/app/views/components/has_many_panel/has_many_panel_component.html.erb +25 -0
- data/app/views/components/has_many_panel/has_many_panel_component.rb +16 -0
- data/app/views/components/header/header_component.rb +3 -3
- data/app/views/components/interactive_action_form/interactive_action_form_component.rb +3 -3
- data/app/views/components/nav_grid_menu/nav_grid_menu_component.html.erb +24 -0
- data/app/views/components/nav_grid_menu/nav_grid_menu_component.rb +23 -0
- data/app/views/components/nav_grid_menu_item/nav_grid_menu_item_component.html.erb +4 -0
- data/app/views/components/nav_grid_menu_item/nav_grid_menu_item_component.rb +20 -0
- data/app/views/components/nav_user/nav_user_component.html.erb +50 -0
- data/app/views/components/nav_user/nav_user_component.rb +32 -0
- data/app/views/components/nav_user_link/nav_user_link_component.html.erb +7 -0
- data/app/views/components/nav_user_link/nav_user_link_component.rb +23 -0
- data/app/views/components/nav_user_section/nav_user_section_component.html.erb +7 -0
- data/app/views/components/nav_user_section/nav_user_section_component.rb +18 -0
- data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_component.html.erb +1 -3
- data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_component.rb +11 -5
- data/app/views/components/pagination/pagination_component.html.erb +1 -1
- data/app/views/components/pagination/pagination_component.rb +10 -7
- data/app/views/components/panel/panel_component.html.erb +13 -6
- data/app/views/components/panel/panel_component.rb +11 -5
- data/app/views/components/resource_header/resource_header_component.html.erb +81 -0
- data/app/views/components/resource_header/resource_header_component.rb +20 -0
- data/app/views/components/resource_layout/resource_layout_component.html.erb +32 -0
- data/app/views/components/resource_layout/resource_layout_component.rb +39 -0
- data/app/views/components/sidebar/sidebar_component.html.erb +3 -33
- data/app/views/components/sidebar/sidebar_component.rb +3 -3
- data/app/views/components/sidebar_menu/sidebar_menu_component.html.erb +4 -2
- data/app/views/components/sidebar_menu/sidebar_menu_component.rb +10 -6
- data/app/views/components/sidebar_menu_item/sidebar_menu_item_component.html.erb +63 -71
- data/app/views/components/sidebar_menu_item/sidebar_menu_item_component.rb +27 -8
- data/app/views/components/skeleton/table/table_component.html.erb +1 -1
- data/app/views/components/skeleton/table/table_component.rb +3 -3
- data/app/views/components/table/table_component.html.erb +40 -89
- data/app/views/components/table/table_component.rb +124 -28
- data/app/views/components/table_search_input/table_search_input_component.html.erb +1 -1
- data/app/views/components/table_search_input/table_search_input_component.rb +11 -6
- data/app/views/components/table_toolbar/table_toolbar_component.html.erb +1 -1
- data/app/views/components/table_toolbar/table_toolbar_component.rb +11 -3
- data/app/views/components/toolbar/toolbar_component.html.erb +2 -2
- data/app/views/components/toolbar/toolbar_component.rb +16 -8
- data/app/views/layouts/resource.html copy.erb +2 -2
- data/app/views/layouts/resource.html.erb +21 -37
- data/app/views/layouts/rodauth.html.erb +32 -25
- data/app/views/resource/_interactive_resource_action_form.html.erb +1 -1
- data/app/views/resource/_resource_details.html.erb +8 -5
- data/app/views/resource/_resource_table.html.erb +70 -1
- data/app/views/resource/interactive_resource_collection_action.html.erb +1 -0
- data/app/views/resource/interactive_resource_record_action.html.erb +1 -0
- data/app/views/resource/interactive_resource_recordless_action.html.erb +1 -0
- data/app/views/resource/new.html.erb +1 -0
- data/app/views/rodauth/add_recovery_codes.html.erb +8 -7
- data/app/views/rodauth/otp_auth.html.erb +1 -1
- data/app/views/rodauth/otp_setup.html.erb +10 -8
- data/config/initializers/simple_form.rb +22 -2
- data/esbuild.config.js +35 -31
- data/lib/generators/pu/core/assets/assets_generator.rb +41 -0
- data/lib/generators/pu/core/assets/templates/tailwind.config.js +18 -0
- data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +3 -0
- data/lib/generators/pu/core/ruby/ruby_generator.rb +30 -0
- data/lib/generators/pu/core/ruby/templates/.keep +0 -0
- data/lib/generators/pu/docker/install/install_generator.rb +35 -0
- data/lib/generators/pu/docker/install/templates/.keep +0 -0
- data/lib/generators/pu/docker/install/templates/Dockerfile.dev.tt +30 -0
- data/lib/generators/pu/docker/install/templates/Dockerfile.tt +75 -0
- data/lib/generators/pu/docker/install/templates/bin/console +3 -0
- data/lib/generators/pu/docker/install/templates/bin/restart +3 -0
- data/lib/generators/pu/docker/install/templates/bin/shell +3 -0
- data/lib/generators/pu/docker/install/templates/docker-compose.yml +29 -0
- data/lib/generators/pu/gem/dotenv/dotenv_generator.rb +32 -0
- data/lib/generators/pu/gem/dotenv/templates/.env +6 -0
- data/lib/generators/pu/gem/dotenv/templates/.env.local +5 -0
- data/lib/generators/pu/gem/dotenv/templates/.env.local.template +5 -0
- data/lib/generators/pu/gem/dotenv/templates/.env.template +6 -0
- data/lib/generators/pu/gem/dotenv/templates/.keep +0 -0
- data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +21 -0
- data/lib/generators/pu/gem/redis/redis_generator.rb +22 -0
- data/lib/generators/pu/gem/redis/templates/.keep +0 -0
- data/lib/generators/pu/gen/component/component_generator.rb +13 -10
- data/lib/generators/pu/gen/component/templates/component.html.erb.tt +1 -1
- data/lib/generators/pu/gen/component/templates/component.rb.tt +10 -4
- data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +154 -32
- data/lib/generators/pu/lib/plutonium_generators/generator.rb +6 -6
- data/lib/generators/pu/lib/plutonium_generators/installer.rb +1 -1
- data/lib/generators/pu/pkg/app/app_generator.rb +4 -4
- data/lib/generators/pu/pkg/app/templates/app/controllers/concerns/controller.rb.tt +28 -0
- data/lib/generators/pu/pkg/app/templates/app/controllers/controller.rb.tt +5 -0
- data/lib/generators/pu/pkg/app/templates/app/controllers/dashboard_controller.rb.tt +1 -1
- data/lib/generators/pu/res/conn/conn_generator.rb +4 -4
- data/lib/generators/pu/res/conn/templates/app/controllers/resource_controller.rb.tt +1 -1
- data/lib/generators/pu/res/model/model_generator.rb +3 -3
- data/lib/generators/pu/res/scaffold/templates/policy.rb.tt +6 -0
- data/lib/generators/pu/rodauth/account_generator.rb +10 -10
- data/lib/generators/pu/rodauth/install_generator.rb +9 -2
- data/lib/generators/pu/rodauth/migration/sequel/audit_logging.erb +2 -2
- data/lib/generators/pu/rodauth/migration_generator.rb +1 -1
- data/lib/generators/pu/rodauth/templates/app/{misc → rodauth}/account_rodauth_plugin.rb.tt +2 -2
- data/lib/generators/pu/rodauth/templates/app/{misc → rodauth}/rodauth_plugin.rb.tt +0 -3
- data/lib/generators/pu/rodauth/templates/db/migrate/install_rodauth.rb.tt +5 -0
- data/lib/generators/pu/service/postgres/postgres_generator.rb +61 -0
- data/lib/generators/pu/service/postgres/templates/.keep +0 -0
- data/lib/generators/pu/service/postgres/templates/bin/initdb.d/create-multiple-postgresql-databases.sh +22 -0
- data/lib/generators/pu/service/postgres/templates/database.yml.tt +93 -0
- data/lib/generators/pu/service/sidekiq/sidekiq_generator.rb +57 -0
- data/lib/generators/pu/service/sidekiq/templates/.keep +0 -0
- data/lib/generators/pu/service/sidekiq/templates/app/sidekiq/sidekiq_job.rb +3 -0
- data/lib/generators/pu/service/sidekiq/templates/config/initializers/sidekiq.rb +53 -0
- data/lib/generators/pu/service/sidekiq/templates/config/sidekiq.yml +6 -0
- data/lib/plutonium/config.rb +2 -9
- data/lib/plutonium/core/associations/renderers/basic_renderer.rb +28 -0
- data/lib/plutonium/core/associations/renderers/factory.rb +36 -0
- data/lib/plutonium/core/associations/renderers/has_many_renderer.rb +16 -0
- data/lib/plutonium/core/autodiscovery/association_renderer_discoverer.rb +31 -0
- data/lib/plutonium/core/controllers/authorizable.rb +13 -17
- data/lib/plutonium/core/controllers/base.rb +3 -7
- data/lib/plutonium/core/controllers/entity_scoping.rb +3 -3
- data/lib/plutonium/core/controllers/presentable.rb +6 -1
- data/lib/plutonium/core/definers/association_renderer_definer.rb +33 -0
- data/lib/plutonium/core/fields/inputs/checkbox_input.rb +13 -0
- data/lib/plutonium/core/fields/inputs/factory.rb +1 -0
- data/lib/plutonium/core/fields/inputs/polymorphic_belongs_to_association_input.rb +1 -1
- data/lib/plutonium/core/ui/detail.rb +1 -0
- data/lib/plutonium/helpers/application_helper.rb +8 -9
- data/lib/plutonium/helpers/assets_helper.rb +33 -0
- data/lib/plutonium/helpers/display_helper.rb +13 -0
- data/lib/plutonium/helpers/form_helper.rb +1 -1
- data/lib/plutonium/helpers.rb +1 -0
- data/lib/plutonium/icons.rb +12 -5
- data/lib/plutonium/pkg/app.rb +10 -0
- data/lib/plutonium/pundit/context.rb +18 -0
- data/lib/plutonium/pundit/policy_finder.rb +25 -0
- data/lib/plutonium/railtie.rb +24 -8
- data/lib/plutonium/reloader.rb +18 -7
- data/lib/plutonium/resource/controller.rb +5 -0
- data/lib/plutonium/resource/policy.rb +69 -47
- data/lib/plutonium/resource/presenter.rb +1 -0
- data/lib/plutonium/resource/query_object.rb +139 -130
- data/lib/plutonium/rodauth/controller_methods.rb +7 -3
- data/lib/plutonium/version.rb +1 -1
- data/lib/plutonium.rb +10 -54
- data/lib/tasks/create_rodauth_admin.rake +16 -0
- data/package-lock.json +782 -17
- data/package.json +31 -8
- data/postcss.config.js +17 -7
- data/src/.npmignore +2 -0
- data/src/js/controllers/color_mode_controller.js +41 -0
- data/src/js/controllers/frame_navigator_controller.js +99 -0
- data/src/js/controllers/has_many_panel_controller.js +8 -0
- data/src/js/controllers/nav_grid_menu_controller.js +8 -0
- data/src/js/controllers/nav_grid_menu_item_controller.js +8 -0
- data/{app/views/components/tab_bar/tab_bar_controller.js → src/js/controllers/nav_user_controller.js} +2 -2
- data/src/js/controllers/nav_user_link_controller.js +8 -0
- data/src/js/controllers/nav_user_section_controller.js +8 -0
- data/src/js/controllers/register_controllers.js +45 -0
- data/{app/assets/javascripts → src/js}/controllers/resource_dismiss_controller.js +2 -0
- data/{app/assets/javascripts → src/js}/controllers/resource_drop_down_controller.js +2 -0
- data/src/js/controllers/resource_header_controller.js +8 -0
- data/src/js/controllers/resource_layout_controller.js +8 -0
- data/src/js/controllers/sidebar_menu_controller.js +8 -0
- data/src/js/controllers/sidebar_menu_item_controller.js +8 -0
- data/src/js/core.js +4 -0
- data/{app/assets/javascripts/plutonium-app.js → src/js/plutonium.js} +1 -1
- data/{app/assets/javascripts → src/js}/turbo/turbo_debug.js +2 -4
- data/tailwind.config.js +85 -84
- metadata +106 -41
- data/app/assets/build/plutonium.js +0 -5122
- data/app/assets/javascripts/controllers/index.js +0 -34
- data/app/assets/javascripts/plutonium.js +0 -1
- data/app/views/application/_color_modes.html.erb +0 -57
- data/app/views/components/tab_bar/tab_bar_component.html.erb +0 -11
- data/app/views/components/tab_bar/tab_bar_component.rb +0 -9
- data/app/views/resource/_nav_user.html.erb +0 -4
- data/app/views/resource/_tab_menu.html.erb +0 -13
- data/css.manifest +0 -3
- data/js.manifest +0 -4
- data/lib/generators/pu/pkg/app/templates/app/controllers/app_controller.rb.tt +0 -5
- data/lib/generators/pu/pkg/app/templates/app/controllers/package_controller.rb.tt +0 -26
- data/public/plutonium-assets/application.css +0 -25086
- data/public/plutonium-assets/plutonium-app-36KN5FVJ.js +0 -6
- data/public/plutonium-assets/plutonium-app-36KN5FVJ.js.map +0 -7
- data/public/plutonium-assets/plutonium-app-6WILQCTT.js +0 -39
- data/public/plutonium-assets/plutonium-app-6WILQCTT.js.map +0 -7
- data/public/plutonium-assets/plutonium.2d4f0c333cd000051d3b.css +0 -3424
- data/public/plutonium-assets/plutonium.50232e35b5495f5ad90d.css +0 -3415
- /data/{app/assets/build → lib/generators/pu/core/assets/templates}/.keep +0 -0
- /data/lib/generators/pu/rodauth/templates/app/{misc → rodauth}/rodauth_app.rb.tt +0 -0
- /data/{app/assets/stylesheets → src/css}/plutonium.css +0 -0
- /data/{app/views/components/form → src/js/controllers}/form_controller.js +0 -0
- /data/{app/views/components/interactive_action_form → src/js/controllers}/interactive_action_form_controller.js +0 -0
- /data/{app/views/components/nested_resource_form_fields → src/js/controllers}/nested_resource_form_fields_controller.js +0 -0
- /data/{app/views/components/table → src/js/controllers}/table_controller.js +0 -0
- /data/{app/views/components/table_search_input → src/js/controllers}/table_search_input_controller.js +0 -0
- /data/{app/views/components/table_toolbar → src/js/controllers}/table_toolbar_controller.js +0 -0
- /data/{app/views/components/toolbar → src/js/controllers}/toolbar_controller.js +0 -0
- /data/{app/assets/javascripts → src/js}/turbo/index.js +0 -0
- /data/{app/assets/javascripts → src/js}/turbo/turbo_actions.js +0 -0
- /data/{app/assets/javascripts → src/js}/turbo/turbo_frame_monkey_patch.js +0 -0
@@ -1,61 +1,57 @@
|
|
1
|
-
# TODO: make standard query type names e.g. search and scope configurable
|
2
|
-
|
3
1
|
module Plutonium
|
4
2
|
module Resource
|
5
|
-
# The QueryObject class is responsible for handling various query types and applying them to the given scope.
|
6
3
|
class QueryObject
|
7
4
|
class << self
|
8
5
|
end
|
9
6
|
|
10
|
-
# The Query class serves as a base for different types of queries.
|
11
7
|
class Query
|
12
8
|
include Plutonium::Core::Definers::InputDefiner
|
13
9
|
|
14
|
-
# Applies the query to the given scope
|
10
|
+
# Applies the query to the given scope using the provided parameters.
|
15
11
|
#
|
16
|
-
# @param scope [Object]
|
17
|
-
# @param params [Hash]
|
18
|
-
# @return [Object]
|
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.
|
19
15
|
def apply(scope, params)
|
20
16
|
params = extract_query_params(params)
|
21
|
-
|
17
|
+
|
18
|
+
if input_definitions.size == params.size
|
19
|
+
apply_internal(scope, params)
|
20
|
+
else
|
21
|
+
scope
|
22
|
+
end
|
22
23
|
end
|
23
24
|
|
24
25
|
private
|
25
26
|
|
26
|
-
#
|
27
|
+
# Abstract method to apply the query logic to the scope.
|
28
|
+
# Should be implemented by subclasses.
|
27
29
|
#
|
28
|
-
# @param scope [Object]
|
29
|
-
# @param params [Hash]
|
30
|
-
# @raise [NotImplementedError]
|
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.
|
31
33
|
def apply_internal(scope, params)
|
32
34
|
raise NotImplementedError, "#{self.class}#apply_internal"
|
33
35
|
end
|
34
36
|
|
35
|
-
# Extracts
|
37
|
+
# Extracts query parameters based on the defined inputs.
|
36
38
|
#
|
37
|
-
# @param params [Hash]
|
38
|
-
# @return [Hash]
|
39
|
+
# @param params [Hash] The parameters to extract.
|
40
|
+
# @return [Hash] The extracted and symbolized parameters.
|
39
41
|
def extract_query_params(params)
|
40
42
|
input_definitions.collect_all(params).compact.symbolize_keys
|
41
43
|
end
|
42
44
|
|
43
|
-
#
|
44
|
-
|
45
|
-
# @return [Class, nil] the resource class
|
46
|
-
def resource_class
|
47
|
-
nil
|
48
|
-
end
|
45
|
+
# @return [nil] The resource class (default implementation returns nil).
|
46
|
+
def resource_class = nil
|
49
47
|
end
|
50
48
|
|
51
|
-
# The ScopeQuery class represents a query based on a scope.
|
52
49
|
class ScopeQuery < Query
|
53
50
|
attr_reader :name
|
54
51
|
|
55
|
-
# Initializes a ScopeQuery.
|
52
|
+
# Initializes a ScopeQuery with a given name.
|
56
53
|
#
|
57
|
-
# @param name [Symbol]
|
58
|
-
# @yield [self] optional block to configure the query
|
54
|
+
# @param name [Symbol] The name of the scope.
|
59
55
|
def initialize(name)
|
60
56
|
@name = name
|
61
57
|
yield self if block_given?
|
@@ -63,24 +59,22 @@ module Plutonium
|
|
63
59
|
|
64
60
|
private
|
65
61
|
|
66
|
-
# Applies the scope query to the given scope
|
62
|
+
# Applies the scope query to the given scope.
|
67
63
|
#
|
68
|
-
# @param scope [Object]
|
69
|
-
# @param params [Hash]
|
70
|
-
# @return [Object]
|
64
|
+
# @param scope [Object] The initial scope.
|
65
|
+
# @param params [Hash] The parameters for the query.
|
66
|
+
# @return [Object] The modified scope.
|
71
67
|
def apply_internal(scope, params)
|
72
68
|
scope.send(name, **params)
|
73
69
|
end
|
74
70
|
end
|
75
71
|
|
76
|
-
# The BlockQuery class represents a query based on a block.
|
77
72
|
class BlockQuery < Query
|
78
73
|
attr_reader :body
|
79
74
|
|
80
|
-
# Initializes a BlockQuery.
|
75
|
+
# Initializes a BlockQuery with a given block of code.
|
81
76
|
#
|
82
|
-
# @param body [Proc]
|
83
|
-
# @yield [self] optional block to configure the query
|
77
|
+
# @param body [Proc] The block of code for the query.
|
84
78
|
def initialize(body)
|
85
79
|
@body = body
|
86
80
|
yield self if block_given?
|
@@ -88,22 +82,26 @@ module Plutonium
|
|
88
82
|
|
89
83
|
private
|
90
84
|
|
91
|
-
# Applies the block query to the given scope
|
85
|
+
# Applies the block query to the given scope.
|
92
86
|
#
|
93
|
-
# @param scope [Object]
|
94
|
-
# @param params [Hash]
|
95
|
-
# @return [Object]
|
87
|
+
# @param scope [Object] The initial scope.
|
88
|
+
# @param params [Hash] The parameters for the query.
|
89
|
+
# @return [Object] The modified scope.
|
96
90
|
def apply_internal(scope, params)
|
97
|
-
|
91
|
+
if body.arity == 1
|
92
|
+
body.call(scope)
|
93
|
+
else
|
94
|
+
body.call(scope, **params)
|
95
|
+
end
|
98
96
|
end
|
99
97
|
end
|
100
98
|
|
101
|
-
attr_reader :search_filter, :search_query
|
99
|
+
attr_reader :search_filter, :search_query
|
102
100
|
|
103
|
-
# Initializes a QueryObject.
|
101
|
+
# Initializes a QueryObject with the given context and parameters.
|
104
102
|
#
|
105
|
-
# @param context [Object]
|
106
|
-
# @param params [Hash]
|
103
|
+
# @param context [Object] The context in which the query object is used.
|
104
|
+
# @param params [Hash] The parameters for initialization.
|
107
105
|
def initialize(context, params)
|
108
106
|
@context = context
|
109
107
|
|
@@ -116,59 +114,43 @@ module Plutonium
|
|
116
114
|
extract_sort_params(params)
|
117
115
|
end
|
118
116
|
|
119
|
-
# Builds a URL with the
|
117
|
+
# Builds a URL with the given options for search and sorting.
|
120
118
|
#
|
121
|
-
# @param options [Hash]
|
122
|
-
# @return [String]
|
119
|
+
# @param options [Hash] The options for building the URL.
|
120
|
+
# @return [String] The constructed URL with query parameters.
|
123
121
|
def build_url(**options)
|
124
122
|
q = {}
|
125
|
-
|
126
|
-
q[:
|
123
|
+
|
124
|
+
q[:search] = options.key?(:search) ? options[:search].presence : search_query
|
125
|
+
q[:scope] = options.key?(:scope) ? options[:scope].presence : selected_scope_filter
|
126
|
+
|
127
127
|
q[:sort_directions] = selected_sort_directions.dup
|
128
128
|
q[:sort_fields] = selected_sort_fields.dup
|
129
|
-
|
130
|
-
if (sort = options[:sort])
|
131
|
-
handle_sort_options(q, sort, options[:reset])
|
132
|
-
end
|
129
|
+
handle_sort_options!(q, options)
|
133
130
|
|
134
131
|
"?#{{q: q}.to_param}"
|
135
132
|
end
|
136
133
|
|
137
|
-
# Applies the
|
134
|
+
# Applies the defined filters and sorts to the given scope.
|
138
135
|
#
|
139
|
-
# @param scope [Object]
|
140
|
-
# @return [Object]
|
136
|
+
# @param scope [Object] The initial scope to which filters and sorts are applied.
|
137
|
+
# @return [Object] The modified scope.
|
141
138
|
def apply(scope)
|
142
139
|
scope = search_filter.apply(scope, {search: search_query}) if search_filter.present?
|
143
140
|
scope = scope_definitions[selected_scope_filter].apply(scope, {}) if selected_scope_filter.present?
|
144
|
-
|
141
|
+
apply_sorts(scope)
|
145
142
|
end
|
146
143
|
|
147
|
-
|
148
|
-
#
|
149
|
-
# @return [HashWithIndifferentAccess] the scope definitions
|
150
|
-
def scope_definitions
|
151
|
-
@scope_definitions ||= {}.with_indifferent_access
|
152
|
-
end
|
144
|
+
def scope_definitions = @scope_definitions ||= {}.with_indifferent_access
|
153
145
|
|
154
|
-
|
155
|
-
#
|
156
|
-
# @return [HashWithIndifferentAccess] the filter definitions
|
157
|
-
def filter_definitions
|
158
|
-
@filter_definitions ||= {}.with_indifferent_access
|
159
|
-
end
|
146
|
+
def filter_definitions = @filter_definitions ||= {}.with_indifferent_access
|
160
147
|
|
161
|
-
|
162
|
-
#
|
163
|
-
# @return [HashWithIndifferentAccess] the sort definitions
|
164
|
-
def sort_definitions
|
165
|
-
@sort_definitions ||= {}.with_indifferent_access
|
166
|
-
end
|
148
|
+
def sort_definitions = @sort_definitions ||= {}.with_indifferent_access
|
167
149
|
|
168
|
-
#
|
150
|
+
# Provides sorting parameters for the given field name.
|
169
151
|
#
|
170
|
-
# @param name [Symbol]
|
171
|
-
# @return [Hash, nil]
|
152
|
+
# @param name [Symbol, String] The name of the field to sort.
|
153
|
+
# @return [Hash, nil] The sorting parameters including URL and direction.
|
172
154
|
def sort_params_for(name)
|
173
155
|
return unless sort_definitions[name]
|
174
156
|
|
@@ -182,59 +164,64 @@ module Plutonium
|
|
182
164
|
|
183
165
|
private
|
184
166
|
|
185
|
-
|
167
|
+
attr_reader :context, :selected_sort_fields, :selected_sort_directions, :selected_scope_filter
|
168
|
+
|
169
|
+
# Defines standard filters.
|
186
170
|
def define_filters
|
171
|
+
# Implement filter definitions if needed
|
187
172
|
end
|
188
173
|
|
189
|
-
#
|
174
|
+
# Defines standard scopes.
|
190
175
|
def define_scopes
|
176
|
+
# Implement scope definitions if needed
|
191
177
|
end
|
192
178
|
|
193
|
-
#
|
179
|
+
# Defines standard sorters.
|
194
180
|
def define_sorters
|
181
|
+
# Implement sorter definitions if needed
|
195
182
|
end
|
196
183
|
|
197
|
-
# Defines standard queries.
|
184
|
+
# Defines standard queries for search and scope.
|
198
185
|
def define_standard_queries
|
199
186
|
define_search(:search) if resource_class.respond_to?(:search)
|
200
187
|
end
|
201
188
|
|
202
|
-
# Defines a filter.
|
189
|
+
# Defines a filter with the given name and body.
|
203
190
|
#
|
204
|
-
# @param name [Symbol]
|
205
|
-
# @param body [Proc, nil]
|
206
|
-
# @yield [Query] optional block to configure the query
|
191
|
+
# @param name [Symbol] The name of the filter.
|
192
|
+
# @param body [Proc, nil] The body of the filter.
|
207
193
|
def define_filter(name, body = nil, &block)
|
208
194
|
body ||= name
|
209
195
|
filter_definitions[name] = build_query(body, &block)
|
210
196
|
end
|
211
197
|
|
212
|
-
# Defines a scope.
|
198
|
+
# Defines a scope with the given name and body.
|
213
199
|
#
|
214
|
-
# @param name [Symbol]
|
215
|
-
# @param body [Proc, nil]
|
200
|
+
# @param name [Symbol] The name of the scope.
|
201
|
+
# @param body [Proc, nil] The body of the scope.
|
216
202
|
def define_scope(name, body = nil)
|
217
203
|
body ||= name
|
218
204
|
scope_definitions[name] = build_query(body)
|
219
205
|
end
|
220
206
|
|
221
|
-
# Defines a sort.
|
207
|
+
# Defines a sort with the given name and body.
|
222
208
|
#
|
223
|
-
# @param name [Symbol]
|
224
|
-
# @param body [Proc, nil]
|
225
|
-
def
|
209
|
+
# @param name [Symbol] The name of the sort.
|
210
|
+
# @param body [Proc, nil] The body of the sort.
|
211
|
+
def define_sorter(name, body = nil)
|
226
212
|
if body.nil?
|
227
213
|
sort_field = determine_sort_field(name)
|
228
214
|
body = ->(scope, direction:) { scope.order(sort_field => direction) }
|
229
215
|
end
|
216
|
+
|
230
217
|
sort_definitions[name] = build_query(body) do |query|
|
231
218
|
query.define_input :direction
|
232
219
|
end
|
233
220
|
end
|
234
221
|
|
235
|
-
# Defines a search filter.
|
222
|
+
# Defines a search filter with the given body.
|
236
223
|
#
|
237
|
-
# @param body [Proc]
|
224
|
+
# @param body [Proc, Symbol] The body of the search filter.
|
238
225
|
def define_search(body)
|
239
226
|
@search_filter = build_query(body) do |query|
|
240
227
|
query.define_input :search
|
@@ -243,7 +230,7 @@ module Plutonium
|
|
243
230
|
|
244
231
|
# Extracts filter parameters from the given params.
|
245
232
|
#
|
246
|
-
# @param params [Hash]
|
233
|
+
# @param params [Hash] The parameters to extract.
|
247
234
|
def extract_filter_params(params)
|
248
235
|
@search_query = params[:search]
|
249
236
|
@selected_scope_filter = params[:scope]
|
@@ -251,39 +238,35 @@ module Plutonium
|
|
251
238
|
|
252
239
|
# Extracts sort parameters from the given params.
|
253
240
|
#
|
254
|
-
# @param params [Hash]
|
241
|
+
# @param params [Hash] The parameters to extract.
|
255
242
|
def extract_sort_params(params)
|
256
|
-
@selected_sort_fields = Array(params[:sort_fields])
|
257
|
-
@
|
243
|
+
@selected_sort_fields = Array(params[:sort_fields])
|
244
|
+
@selected_sort_fields &= sort_definitions.keys
|
245
|
+
|
246
|
+
@selected_sort_directions = extract_sort_directions(params)
|
258
247
|
end
|
259
248
|
|
260
|
-
# Builds a query object.
|
249
|
+
# Builds a query object based on the given body and optional block.
|
261
250
|
#
|
262
|
-
# @param body [
|
263
|
-
# @
|
264
|
-
# @return [Query]
|
251
|
+
# @param body [Proc, Symbol] The body of the query.
|
252
|
+
# @yieldparam query [Query] The query object.
|
253
|
+
# @return [Query] The constructed query object.
|
265
254
|
def build_query(body, &block)
|
266
255
|
case body
|
267
256
|
when Symbol
|
268
257
|
raise "Cannot find scope :#{body} on #{resource_class}" unless resource_class.respond_to?(body)
|
258
|
+
|
269
259
|
ScopeQuery.new(body, &block)
|
270
260
|
else
|
271
261
|
BlockQuery.new(body, &block)
|
272
262
|
end
|
273
263
|
end
|
274
264
|
|
275
|
-
#
|
265
|
+
# Determines the sort field for the given name.
|
276
266
|
#
|
277
|
-
# @
|
278
|
-
|
279
|
-
|
280
|
-
end
|
281
|
-
|
282
|
-
# Determines the sort field for a given name.
|
283
|
-
#
|
284
|
-
# @param name [Symbol] the name of the sort field
|
285
|
-
# @return [Symbol] the determined sort field
|
286
|
-
# @raise [RuntimeError] if unable to determine sort logic for the field
|
267
|
+
# @param name [Symbol, String] The name of the field.
|
268
|
+
# @return [Symbol] The sort field.
|
269
|
+
# @raise [RuntimeError] If unable to determine sort logic.
|
287
270
|
def determine_sort_field(name)
|
288
271
|
if resource_class.primary_key == name.to_s || resource_class.content_column_field_names.include?(name)
|
289
272
|
name
|
@@ -294,39 +277,65 @@ module Plutonium
|
|
294
277
|
end
|
295
278
|
end
|
296
279
|
|
297
|
-
#
|
280
|
+
# Extracts sort directions from the given params.
|
281
|
+
#
|
282
|
+
# @param params [Hash] The parameters to extract.
|
283
|
+
# @return [Hash] The extracted sort directions.
|
284
|
+
def extract_sort_directions(params)
|
285
|
+
params[:sort_directions]&.slice(*sort_definitions.keys) || {}
|
286
|
+
end
|
287
|
+
|
288
|
+
# Handles the sort options for building the URL.
|
289
|
+
#
|
290
|
+
# @param query_params [Hash] The query parameters.
|
291
|
+
# @param options [Hash] The options for sorting.
|
292
|
+
def handle_sort_options!(query_params, options)
|
293
|
+
if (sort = options[:sort])
|
294
|
+
handle_sort_reset!(query_params, sort, options[:reset])
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# Handles the reset option for sorting.
|
298
299
|
#
|
299
|
-
# @param
|
300
|
-
# @param sort [Symbol]
|
301
|
-
# @param reset [Boolean]
|
302
|
-
def
|
300
|
+
# @param query_params [Hash] The query parameters.
|
301
|
+
# @param sort [Symbol, String] The sort field.
|
302
|
+
# @param reset [Boolean] Whether to reset the sort.
|
303
|
+
def handle_sort_reset!(query_params, sort, reset)
|
303
304
|
if reset
|
304
|
-
|
305
|
-
|
305
|
+
query_params[:sort_fields].delete_if { |e| e == sort.to_s }
|
306
|
+
query_params[:sort_directions].delete(sort)
|
306
307
|
else
|
307
|
-
|
308
|
+
query_params[:sort_fields] << sort.to_s unless query_params[:sort_fields].include?(sort.to_s)
|
309
|
+
|
308
310
|
sort_direction = selected_sort_directions[sort]
|
309
|
-
|
310
|
-
"ASC"
|
311
|
+
if sort_direction.nil?
|
312
|
+
query_params[:sort_directions][sort] = "ASC"
|
313
|
+
elsif sort_direction == "ASC"
|
314
|
+
query_params[:sort_directions][sort] = "DESC"
|
311
315
|
else
|
312
|
-
|
316
|
+
query_params[:sort_fields].delete_if { |e| e == sort.to_s }
|
317
|
+
query_params[:sort_directions].delete(sort)
|
313
318
|
end
|
314
|
-
query[:sort_fields].delete_if { |e| e == sort.to_s } if query[:sort_directions][sort] == "ASC"
|
315
319
|
end
|
316
320
|
end
|
317
321
|
|
318
|
-
# Applies sorters to the scope.
|
322
|
+
# Applies the defined sorters to the given scope.
|
319
323
|
#
|
320
|
-
# @param scope [Object]
|
321
|
-
# @return [Object]
|
322
|
-
def
|
324
|
+
# @param scope [Object] The initial scope.
|
325
|
+
# @return [Object] The modified scope.
|
326
|
+
def apply_sorts(scope)
|
323
327
|
selected_sort_fields.each do |name|
|
324
328
|
sorter = sort_definitions[name]
|
325
329
|
next unless sorter.present?
|
326
|
-
|
330
|
+
|
331
|
+
params = {direction: selected_sort_directions[name] || "ASC"}
|
332
|
+
scope = sorter.apply(scope, params)
|
327
333
|
end
|
328
334
|
scope
|
329
335
|
end
|
336
|
+
|
337
|
+
# @return [Object] The resource class from the context.
|
338
|
+
def resource_class = context.resource_class
|
330
339
|
end
|
331
340
|
end
|
332
341
|
end
|
@@ -4,15 +4,19 @@ module Plutonium
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
included do
|
7
|
+
helper Plutonium::Helpers::ApplicationHelper
|
8
|
+
helper Plutonium::Helpers::ComponentHelper
|
9
|
+
helper Plutonium::Helpers::AssetsHelper
|
10
|
+
|
7
11
|
layout "rodauth"
|
8
12
|
append_view_path File.expand_path("app/views", Plutonium.root)
|
9
|
-
helper_method :
|
13
|
+
helper_method :root_path
|
10
14
|
end
|
11
15
|
|
12
16
|
private
|
13
17
|
|
14
|
-
def
|
15
|
-
|
18
|
+
def root_path
|
19
|
+
"/"
|
16
20
|
end
|
17
21
|
end
|
18
22
|
end
|
data/lib/plutonium/version.rb
CHANGED
data/lib/plutonium.rb
CHANGED
@@ -23,67 +23,23 @@ module Plutonium
|
|
23
23
|
Rails.logger
|
24
24
|
end
|
25
25
|
|
26
|
-
def self.
|
27
|
-
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.stylesheet_link
|
31
|
-
return @stylesheet_link if defined?(@stylesheet_link) && !development?
|
32
|
-
|
33
|
-
if development?
|
34
|
-
base_dir = "/plutonium-assets/build"
|
35
|
-
filename = "plutonium-dev.css"
|
36
|
-
else
|
37
|
-
base_dir = "/plutonium-assets"
|
38
|
-
filename = "plutonium.css"
|
39
|
-
end
|
40
|
-
|
41
|
-
file = stylesheet_manifest[filename]
|
42
|
-
@stylesheet_link = "#{base_dir}/#{file}"
|
26
|
+
def self.application_name
|
27
|
+
@application_name || Rails.application.class.module_parent.name
|
43
28
|
end
|
44
29
|
|
45
|
-
def self.
|
46
|
-
|
47
|
-
|
48
|
-
filename = "plutonium-app.js"
|
49
|
-
base_dir = if development?
|
50
|
-
"/plutonium-assets/build"
|
51
|
-
else
|
52
|
-
"/plutonium-assets"
|
53
|
-
end
|
54
|
-
|
55
|
-
file = script_manifest[filename]
|
56
|
-
@script_link = "#{base_dir}/#{file}"
|
30
|
+
def self.application_name=(application_name)
|
31
|
+
@application_name = application_name
|
57
32
|
end
|
58
33
|
|
59
|
-
def self.
|
60
|
-
"
|
61
|
-
end
|
62
|
-
|
63
|
-
def self.logo_link
|
64
|
-
"/plutonium-assets/plutonium-logo.png"
|
65
|
-
end
|
66
|
-
|
67
|
-
def self.stylesheet_manifest
|
68
|
-
return @stylesheet_manifest if defined?(@stylesheet_manifest) && !development?
|
69
|
-
|
70
|
-
manifest = if development?
|
71
|
-
"css.dev.manifest"
|
72
|
-
else
|
73
|
-
"css.manifest"
|
74
|
-
end
|
75
|
-
@stylesheet_manifest = JSON.parse(File.read(root.join(manifest)))
|
34
|
+
def self.development?
|
35
|
+
ActiveModel::Type::Boolean.new.cast(ENV["PLUTONIUM_DEV"]).present?
|
76
36
|
end
|
77
37
|
|
78
|
-
def self.
|
79
|
-
return
|
38
|
+
def self.eager_load_rails!
|
39
|
+
return if Rails.env.production? && defined?(@rails_eager_loaded)
|
80
40
|
|
81
|
-
|
82
|
-
|
83
|
-
else
|
84
|
-
"js.manifest"
|
85
|
-
end
|
86
|
-
@script_manifest = JSON.parse(File.read(root.join(manifest)))
|
41
|
+
Rails.application.eager_load! unless Rails.application.config.eager_load
|
42
|
+
@rails_eager_loaded = true
|
87
43
|
end
|
88
44
|
end
|
89
45
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
namespace :rodauth do
|
2
|
+
desc "Create a Rodauth admin account"
|
3
|
+
task admin: :environment do
|
4
|
+
# require "rodauth"
|
5
|
+
# require "active_record"
|
6
|
+
require "tty-prompt"
|
7
|
+
|
8
|
+
prompt = TTY::Prompt.new
|
9
|
+
email = ENV["EMAIL"] || prompt.ask("email:", required: true)
|
10
|
+
# password = SecureRandom.hex
|
11
|
+
# password = ENV["PASSWORD"] || prompt.mask("password:", required: true)
|
12
|
+
# password_confirm = ENV["PASSWORD"] || prompt.mask("password:", required: true)
|
13
|
+
|
14
|
+
RodauthApp.rodauth(:admin).create_account(login: email)
|
15
|
+
end
|
16
|
+
end
|