plutonium 0.14.1 → 0.15.0.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README copy.md +1 -1
- data/README.md +1 -1
- data/app/assets/plutonium.css +1 -1
- data/app/views/{application → plutonium}/_resource_header.html copy.erb +1 -1
- data/app/views/{application → plutonium}/_resource_header.html.erb +1 -1
- data/app/views/{application → plutonium}/_resource_sidebar.html.erb +2 -0
- data/app/views/resource/_resource_details.html.erb +1 -36
- data/app/views/resource/_resource_form.html.erb +1 -5
- data/app/views/resource/_resource_table.html.erb +315 -85
- data/app/views/resource/edit.html.erb +1 -5
- data/app/views/resource/index.html.erb +1 -5
- data/app/views/resource/new.html.erb +1 -5
- data/app/views/resource/show.html.erb +1 -5
- data/config/initializers/pagy.rb +1 -0
- data/config/initializers/rabl.rb +27 -20
- data/gemfiles/rails_7.gemfile.lock +5 -1
- data/lib/generators/pu/core/install/templates/app/controllers/plutonium_controller.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +21 -1
- data/lib/generators/pu/core/install/templates/app/definitions/resource_definition.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/models/resource_record.rb.tt +0 -2
- data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +1 -8
- data/lib/generators/pu/eject/shell/shell_generator.rb +2 -2
- data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +1 -1
- data/lib/generators/pu/lib/plutonium_generators/concerns/logger.rb +1 -1
- data/lib/generators/pu/lib/plutonium_generators/generator.rb +5 -3
- data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +26 -2
- data/lib/generators/pu/pkg/{feature/feature_generator.rb → package/package_generator.rb} +4 -4
- data/lib/generators/pu/pkg/{feature → package}/templates/app/controllers/resource_controller.rb.tt +0 -2
- data/lib/generators/pu/pkg/package/templates/app/definitions/resource_definition.rb.tt +4 -0
- data/lib/generators/pu/pkg/package/templates/app/query_objects/resource_query_object.rb.tt +4 -0
- data/lib/generators/pu/pkg/{app/app_generator.rb → portal/portal_generator.rb} +10 -8
- data/lib/generators/pu/pkg/{app → portal}/templates/app/controllers/concerns/controller.rb.tt +3 -7
- data/lib/generators/pu/pkg/{app → portal}/templates/app/controllers/dashboard_controller.rb.tt +1 -1
- data/lib/generators/pu/pkg/portal/templates/app/controllers/plutonium_controller.rb.tt +5 -0
- data/lib/generators/pu/pkg/{app/templates/app/controllers/controller.rb.tt → portal/templates/app/controllers/resource_controller.rb.tt} +1 -1
- data/lib/generators/pu/pkg/portal/templates/app/definitions/resource_definition.rb.tt +4 -0
- data/lib/generators/pu/pkg/{app → portal}/templates/app/views/package/dashboard/index.html.erb +2 -1
- data/lib/generators/pu/res/conn/conn_generator.rb +78 -3
- data/lib/generators/pu/res/conn/templates/app/controllers/resource_controller.rb.tt +1 -1
- data/lib/generators/pu/res/conn/templates/app/definitions/resource_definition.rb.tt +3 -0
- data/lib/generators/pu/res/conn/templates/app/policies/resource_policy.rb.tt +29 -1
- data/lib/generators/pu/res/conn/templates/app/presenters/resource_presenter.rb.tt +1 -1
- data/lib/generators/pu/res/conn/templates/app/query_objects/resource_query_object.rb.tt +1 -1
- data/lib/generators/pu/res/model/model_generator.rb +0 -7
- data/lib/generators/pu/res/model/templates/model.rb.tt +4 -1
- data/lib/generators/pu/res/scaffold/scaffold_generator.rb +22 -4
- data/lib/generators/pu/res/scaffold/templates/controller.rb.tt +0 -1
- data/lib/generators/pu/res/scaffold/templates/definition.rb.tt +4 -0
- data/lib/generators/pu/res/scaffold/templates/policy.rb.tt +2 -2
- data/lib/generators/pu/rodauth/templates/app/controllers/rodauth_controller.rb.tt +1 -1
- data/lib/generators/pu/rodauth/templates/app/rodauth/account_rodauth_plugin.rb.tt +270 -0
- data/lib/plutonium/action/README.md +0 -0
- data/lib/plutonium/action/base.rb +103 -0
- data/lib/plutonium/action/interactive.rb +117 -0
- data/lib/plutonium/action/route_options.rb +65 -0
- data/lib/plutonium/action/simple.rb +8 -0
- data/lib/plutonium/auth.rb +1 -1
- data/lib/plutonium/configuration.rb +0 -8
- data/lib/plutonium/core/actions/collection.rb +1 -1
- data/lib/plutonium/core/associations/renderers/factory.rb +3 -1
- data/lib/plutonium/core/controller.rb +110 -0
- data/lib/plutonium/core/controllers/authorizable.rb +12 -35
- data/lib/plutonium/core/controllers/bootable.rb +38 -7
- data/lib/plutonium/core/controllers/entity_scoping.rb +6 -2
- data/lib/plutonium/core/fields/renderers/association_renderer.rb +1 -1
- data/lib/plutonium/core/ui/collection.rb +1 -1
- data/lib/plutonium/core/ui/detail.rb +1 -1
- data/lib/plutonium/core/ui/form.rb +1 -1
- data/lib/plutonium/definition/actions.rb +50 -0
- data/lib/plutonium/definition/base.rb +92 -0
- data/lib/plutonium/definition/config_attr.rb +30 -0
- data/lib/plutonium/definition/defineable_props.rb +96 -0
- data/lib/plutonium/definition/search.rb +21 -0
- data/lib/plutonium/engine/validator.rb +30 -0
- data/lib/plutonium/engine.rb +25 -0
- data/lib/plutonium/helpers/form_helper.rb +1 -3
- data/lib/plutonium/interaction/README.md +369 -0
- data/lib/plutonium/interaction/base.rb +75 -0
- data/lib/plutonium/interaction/concerns/presentable.rb +61 -0
- data/lib/plutonium/interaction/concerns/workflow_dsl.rb +82 -0
- data/lib/plutonium/interaction/outcome.rb +129 -0
- data/lib/plutonium/interaction/response/base.rb +63 -0
- data/lib/plutonium/interaction/response/null.rb +33 -0
- data/lib/plutonium/interaction/response/redirect.rb +30 -0
- data/lib/plutonium/interaction/response/render.rb +28 -0
- data/lib/plutonium/lib/bit_flags.rb +70 -9
- data/lib/plutonium/{config → lib}/overlayed_hash.rb +1 -1
- data/lib/plutonium/lib/smart_cache.rb +171 -0
- data/lib/plutonium/models/has_cents.rb +170 -0
- data/lib/plutonium/{pkg/base.rb → package/engine.rb} +10 -2
- data/lib/plutonium/{application → portal}/controller.rb +3 -11
- data/lib/plutonium/{application → portal}/dynamic_controllers.rb +4 -4
- data/lib/plutonium/portal/engine.rb +15 -0
- data/lib/plutonium/railtie.rb +33 -1
- data/lib/plutonium/reloader.rb +5 -5
- data/lib/plutonium/resource/controller.rb +51 -34
- data/lib/plutonium/resource/controllers/authorizable.rb +128 -0
- data/lib/plutonium/{core → resource}/controllers/crud_actions.rb +23 -22
- data/lib/plutonium/resource/controllers/defineable.rb +26 -0
- data/lib/plutonium/{core → resource}/controllers/interactive_actions.rb +12 -12
- data/lib/plutonium/resource/controllers/presentable.rb +41 -0
- data/lib/plutonium/resource/controllers/queryable.rb +44 -0
- data/lib/plutonium/resource/definition.rb +6 -0
- data/lib/plutonium/resource/policy.rb +25 -13
- data/lib/plutonium/resource/query_object.rb +50 -51
- data/lib/plutonium/resource/record.rb +6 -89
- data/lib/plutonium/resource/register.rb +82 -0
- data/lib/plutonium/routing/mapper_extensions.rb +1 -1
- data/lib/plutonium/routing/resource_registration.rb +1 -1
- data/lib/plutonium/routing/route_set_extensions.rb +6 -18
- data/lib/plutonium/ui/action_button.rb +125 -0
- data/lib/plutonium/ui/breadcrumbs.rb +163 -0
- data/lib/plutonium/ui/component/base.rb +13 -0
- data/lib/plutonium/ui/component/behaviour.rb +38 -0
- data/lib/plutonium/ui/component/kit.rb +31 -0
- data/lib/plutonium/ui/component/methods.rb +54 -0
- data/lib/plutonium/ui/display/base.rb +25 -0
- data/lib/plutonium/ui/display/component/association.rb +26 -0
- data/lib/plutonium/ui/display/resource.rb +77 -0
- data/lib/plutonium/ui/display/theme.rb +27 -0
- data/lib/plutonium/ui/dyna_frame/content.rb +20 -0
- data/lib/plutonium/ui/empty_card.rb +20 -0
- data/lib/plutonium/ui/form/base.rb +37 -0
- data/lib/plutonium/ui/form/resource.rb +75 -0
- data/lib/plutonium/ui/form/theme.rb +42 -0
- data/lib/plutonium/ui/page/base.rb +112 -0
- data/lib/plutonium/ui/page/edit.rb +23 -0
- data/lib/plutonium/ui/page/index.rb +27 -0
- data/lib/plutonium/ui/page/new.rb +23 -0
- data/lib/plutonium/ui/page/show.rb +27 -0
- data/lib/plutonium/ui/page_header.rb +49 -0
- data/lib/plutonium/ui/table/base.rb +13 -0
- data/lib/plutonium/ui/table/components/pagy_info.rb +70 -0
- data/lib/plutonium/ui/table/components/pagy_page_info.rb +70 -0
- data/lib/plutonium/ui/table/components/pagy_pagination.rb +105 -0
- data/lib/plutonium/ui/table/components/scopes_bar.rb +136 -0
- data/lib/plutonium/ui/table/components/search_bar.rb +158 -0
- data/lib/plutonium/ui/table/display_theme.rb +21 -0
- data/lib/plutonium/ui/table/resource.rb +98 -0
- data/lib/plutonium/ui/table/theme.rb +35 -0
- data/lib/plutonium/ui.rb +9 -0
- data/lib/plutonium/version.rb +5 -1
- data/lib/plutonium.rb +14 -1
- data/package-lock.json +19 -22
- data/package.json +4 -4
- data/src/css/plutonium.css +15 -0
- data/tailwind.options.js +11 -3
- metadata +218 -81
- data/lib/generators/pu/core/install/templates/app/presenters/resource_presenter.rb.tt +0 -2
- data/lib/generators/pu/core/install/templates/app/query_objects/resource_query_object.rb.tt +0 -2
- data/lib/generators/pu/pkg/feature/templates/app/query_objects/resource_query_object.rb.tt +0 -4
- data/lib/plutonium/concerns/resource_validatable.rb +0 -34
- data/lib/plutonium/config.rb +0 -9
- data/lib/plutonium/core/controllers/base.rb +0 -101
- data/lib/plutonium/core/controllers/presentable.rb +0 -65
- data/lib/plutonium/core/controllers/queryable.rb +0 -28
- data/lib/plutonium/pkg/app.rb +0 -35
- data/lib/plutonium/pkg/concerns/resource_validatable.rb +0 -36
- data/lib/plutonium/pkg/feature.rb +0 -18
- data/lib/plutonium/policy/initializer.rb +0 -22
- data/lib/plutonium/policy/scope.rb +0 -19
- data/lib/plutonium/pundit/context.rb +0 -18
- data/lib/plutonium/pundit/policy_finder.rb +0 -25
- data/lib/plutonium/resource/policy_context.rb +0 -5
- data/lib/plutonium/resource_register.rb +0 -83
- data/lib/plutonium/smart_cache.rb +0 -151
- /data/app/views/{application → plutonium}/_flash.html.erb +0 -0
- /data/app/views/{application → plutonium}/_flash_alerts.html.erb +0 -0
- /data/app/views/{application → plutonium}/_flash_toasts.html.erb +0 -0
- /data/lib/generators/pu/pkg/{app/templates/app/views/package → package/templates}/.keep +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/app/interactions/resource_interaction.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/app/models/resource_record.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/app/policies/resource_policy.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/app/presenters/resource_presenter.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/lib/engine.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/app/policies/resource_policy.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/app/presenters/resource_presenter.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/app/query_objects/resource_query_object.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature/templates → portal/templates/app/views/package}/.keep +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/config/routes.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/lib/engine.rb.tt +0 -0
@@ -2,6 +2,7 @@ module Plutonium
|
|
2
2
|
module Resource
|
3
3
|
module Record
|
4
4
|
extend ActiveSupport::Concern
|
5
|
+
include Plutonium::Models::HasCents
|
5
6
|
|
6
7
|
included do
|
7
8
|
scope :from_path_param, ->(param) { where(id: param) }
|
@@ -14,12 +15,12 @@ module Plutonium
|
|
14
15
|
# TODO: add logging
|
15
16
|
# TODO: memoize this
|
16
17
|
|
17
|
-
own_association = klass.
|
18
|
+
own_association = klass.find_association_from_self_to_record(record)
|
18
19
|
if own_association
|
19
20
|
return klass.query_based_on_association(own_association, record)
|
20
21
|
end
|
21
22
|
|
22
|
-
record_association = klass.
|
23
|
+
record_association = klass.find_association_to_self_from_record(record)
|
23
24
|
if record_association
|
24
25
|
# TODO: add a warning here about a potentially poor performing query
|
25
26
|
return where(id: record.public_send(record_association.name))
|
@@ -43,7 +44,7 @@ module Plutonium
|
|
43
44
|
# @param [Proc] scope The scope for the association
|
44
45
|
# @param [Hash] options The options for the association
|
45
46
|
def belongs_to(name, scope = nil, **options)
|
46
|
-
super
|
47
|
+
super
|
47
48
|
|
48
49
|
return unless options[:polymorphic]
|
49
50
|
|
@@ -155,31 +156,10 @@ module Plutonium
|
|
155
156
|
end.compact.to_h
|
156
157
|
end
|
157
158
|
|
158
|
-
# Returns the strong parameters definition for the given attribute names
|
159
|
-
# @param [Array<Symbol>] *attributes Attribute names
|
160
|
-
# @return [Array<Symbol, Hash>] A strong parameters compatible array
|
161
|
-
def strong_parameters_for(*attributes)
|
162
|
-
unbacked = attributes - strong_parameters_definition.keys
|
163
|
-
|
164
|
-
backed = strong_parameters_definition.slice(*attributes).values.reduce(:merge)
|
165
|
-
&.map { |key, value| value.nil? ? key : {key => value} } || {}
|
166
|
-
|
167
|
-
case backed.presence
|
168
|
-
when Hash
|
169
|
-
[*unbacked, **backed]
|
170
|
-
when Array
|
171
|
-
[*unbacked, *backed]
|
172
|
-
when nil
|
173
|
-
unbacked
|
174
|
-
else
|
175
|
-
raise "Unexpected strong parameters definition: #{backed.class}"
|
176
|
-
end
|
177
|
-
end
|
178
|
-
|
179
159
|
# Finds the association to the given record
|
180
160
|
# @param [ActiveRecord::Base] record The record to find the association with
|
181
161
|
# @return [ActiveRecord::Reflection::AssociationReflection, nil]
|
182
|
-
def
|
162
|
+
def find_association_from_self_to_record(record)
|
183
163
|
reflect_on_all_associations.find do |assoc|
|
184
164
|
assoc.klass.name == record.class.name unless assoc.polymorphic?
|
185
165
|
rescue
|
@@ -191,7 +171,7 @@ module Plutonium
|
|
191
171
|
# Finds the association to self in the given record
|
192
172
|
# @param [ActiveRecord::Base] record The record to find the association with
|
193
173
|
# @return [ActiveRecord::Reflection::AssociationReflection, nil]
|
194
|
-
def
|
174
|
+
def find_association_to_self_from_record(record)
|
195
175
|
record.class.reflect_on_all_associations.find do |assoc|
|
196
176
|
assoc.klass.name == name
|
197
177
|
rescue
|
@@ -231,69 +211,6 @@ module Plutonium
|
|
231
211
|
|
232
212
|
private
|
233
213
|
|
234
|
-
# Defines the strong parameters
|
235
|
-
# @return [Hash]
|
236
|
-
def strong_parameters_definition
|
237
|
-
unless Rails.env.local?
|
238
|
-
return @strong_parameters if defined?(@strong_parameters)
|
239
|
-
end
|
240
|
-
|
241
|
-
@strong_parameters = build_strong_parameters
|
242
|
-
end
|
243
|
-
|
244
|
-
# Builds the strong parameters hash
|
245
|
-
# @return [Hash]
|
246
|
-
def build_strong_parameters
|
247
|
-
parameters = content_column_field_names.map do |name|
|
248
|
-
column = columns_hash[name.to_s]
|
249
|
-
type = if column.try(:array?)
|
250
|
-
[]
|
251
|
-
else
|
252
|
-
([:json, :jsonb].include?(column&.type) ? {} : nil)
|
253
|
-
end
|
254
|
-
[name, {name => type}]
|
255
|
-
end.to_h
|
256
|
-
|
257
|
-
parameters.merge!(belongs_to_association_parameters)
|
258
|
-
parameters.merge!(has_many_association_parameters)
|
259
|
-
parameters.merge!(attachment_parameters)
|
260
|
-
parameters.merge!(nested_attributes_parameters)
|
261
|
-
|
262
|
-
parameters
|
263
|
-
end
|
264
|
-
|
265
|
-
# Returns the parameters for belongs_to associations
|
266
|
-
# @return [Hash]
|
267
|
-
def belongs_to_association_parameters
|
268
|
-
reflect_on_all_associations(:belongs_to).map do |reflection|
|
269
|
-
input_param = reflection.options[:foreign_key] || :"#{reflection.name}_id"
|
270
|
-
[reflection.name, {input_param => nil, :"#{reflection.name}_sgid" => nil}]
|
271
|
-
end.to_h
|
272
|
-
end
|
273
|
-
|
274
|
-
# Returns the parameters for has_many associations
|
275
|
-
# @return [Hash]
|
276
|
-
def has_many_association_parameters
|
277
|
-
has_many_association_field_names.map do |name|
|
278
|
-
[name, {"#{name.to_s.singularize}_ids": []}]
|
279
|
-
end.to_h
|
280
|
-
end
|
281
|
-
|
282
|
-
# Returns the parameters for attachments
|
283
|
-
# @return [Hash]
|
284
|
-
def attachment_parameters
|
285
|
-
has_many_attached_field_names.map { |name| [name, {name => []}] }.to_h
|
286
|
-
.merge(has_one_attached_field_names.map { |name| [name, {name => nil}] }.to_h)
|
287
|
-
end
|
288
|
-
|
289
|
-
# Returns the parameters for nested attributes
|
290
|
-
# @return [Hash]
|
291
|
-
def nested_attributes_parameters
|
292
|
-
all_nested_attributes_options.keys.map do |name|
|
293
|
-
[name, {"#{name}_attributes" => {}}]
|
294
|
-
end.to_h
|
295
|
-
end
|
296
|
-
|
297
214
|
# Defines a scope and method for path parameters
|
298
215
|
# @param [Symbol] param_name The name of the parameter
|
299
216
|
def path_parameter(param_name)
|
@@ -0,0 +1,82 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Plutonium
|
4
|
+
module Resource
|
5
|
+
# Resource register manages the registration and lookup of resources.
|
6
|
+
class Register
|
7
|
+
include Plutonium::Lib::SmartCache
|
8
|
+
|
9
|
+
# Custom error class for frozen register operations
|
10
|
+
class FrozenRegisterError < StandardError; end
|
11
|
+
|
12
|
+
def initialize
|
13
|
+
@resources = Set.new
|
14
|
+
@frozen = false
|
15
|
+
end
|
16
|
+
|
17
|
+
# Registers a new resource with the register.
|
18
|
+
#
|
19
|
+
# @param resource [Class] The resource class to be registered.
|
20
|
+
# @raise [FrozenRegisterError] If the register is frozen.
|
21
|
+
# @return [void]
|
22
|
+
def register(resource)
|
23
|
+
raise FrozenRegisterError, "Cannot modify frozen resource register" if @frozen
|
24
|
+
|
25
|
+
@resources.add(resource.to_s)
|
26
|
+
end
|
27
|
+
|
28
|
+
# Returns an array of all registered resource classes and freezes the register.
|
29
|
+
#
|
30
|
+
# @return [Array<Class>] An array of registered resource classes.
|
31
|
+
def resources
|
32
|
+
freeze
|
33
|
+
@resources.map(&:constantize)
|
34
|
+
end
|
35
|
+
memoize_unless_reloading :resources
|
36
|
+
|
37
|
+
# Returns a hash mapping route keys to their corresponding resource classes.
|
38
|
+
# This method will freeze the register if it hasn't been frozen already.
|
39
|
+
#
|
40
|
+
# @return [Hash{Symbol => Class}] A hash where keys are route keys and values are resource classes.
|
41
|
+
def route_key_lookup
|
42
|
+
freeze
|
43
|
+
resources.to_h do |resource|
|
44
|
+
[resource.model_name.singular_route_key.to_sym, resource]
|
45
|
+
end
|
46
|
+
end
|
47
|
+
memoize_unless_reloading :route_key_lookup
|
48
|
+
|
49
|
+
# Clears all registered resources and invalidates the cache.
|
50
|
+
#
|
51
|
+
# @return [void]
|
52
|
+
def clear
|
53
|
+
@resources.clear
|
54
|
+
@frozen = false
|
55
|
+
invalidate_cache
|
56
|
+
end
|
57
|
+
|
58
|
+
# Checks if the register is frozen.
|
59
|
+
#
|
60
|
+
# @return [Boolean] True if the register is frozen, false otherwise.
|
61
|
+
def frozen?
|
62
|
+
@frozen
|
63
|
+
end
|
64
|
+
|
65
|
+
private
|
66
|
+
|
67
|
+
# Freezes the register
|
68
|
+
#
|
69
|
+
# @return [Boolean] Always returns true
|
70
|
+
def freeze
|
71
|
+
@frozen ||= true
|
72
|
+
end
|
73
|
+
|
74
|
+
# Invalidates the memoization cache
|
75
|
+
#
|
76
|
+
# @return [void]
|
77
|
+
def invalidate_cache
|
78
|
+
flush_smart_cache
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
@@ -79,7 +79,7 @@ module Plutonium
|
|
79
79
|
def define_nested_resource_routes(resource)
|
80
80
|
nested_configs = route_set.resource_route_config_for(*resource.has_many_association_routes)
|
81
81
|
nested_configs.each do |nested_config|
|
82
|
-
resources nested_config[:route_name], **nested_config[:route_options] do
|
82
|
+
resources "nested_#{nested_config[:route_name]}", **nested_config[:route_options] do
|
83
83
|
instance_exec(&nested_config[:block]) if nested_config[:block]
|
84
84
|
end
|
85
85
|
end
|
@@ -12,6 +12,9 @@ module Plutonium
|
|
12
12
|
# register_resource SomeModel
|
13
13
|
# end
|
14
14
|
module RouteSetExtensions
|
15
|
+
extend ActiveSupport::Concern
|
16
|
+
include Plutonium::Engine::Validator
|
17
|
+
|
15
18
|
# Clears all registered resources and route configurations.
|
16
19
|
#
|
17
20
|
# This method should be called when you want to reset all registered resources
|
@@ -30,7 +33,7 @@ module Plutonium
|
|
30
33
|
# @return [void]
|
31
34
|
# @yield Executes the given block in the context of route drawing.
|
32
35
|
def draw(&block)
|
33
|
-
if supported_engine?
|
36
|
+
if self.class.supported_engine?(engine)
|
34
37
|
ActiveSupport::Notifications.instrument("plutonium.resource_routes.draw", app: engine.to_s) do
|
35
38
|
super do
|
36
39
|
setup_shared_resource_concerns
|
@@ -48,9 +51,9 @@ module Plutonium
|
|
48
51
|
# @param resource [Class] The resource class to be registered.
|
49
52
|
# @yield An optional block for additional resource configuration.
|
50
53
|
# @return [Hash] The configuration for the registered resource.
|
51
|
-
# @raise [ArgumentError] If the engine
|
54
|
+
# @raise [ArgumentError] If the engine is not supported.
|
52
55
|
def register_resource(resource, &)
|
53
|
-
validate_engine!
|
56
|
+
self.class.validate_engine! engine
|
54
57
|
engine.resource_register.register(resource)
|
55
58
|
|
56
59
|
route_name = resource.model_name.plural
|
@@ -85,21 +88,6 @@ module Plutonium
|
|
85
88
|
@resource_route_config_lookup ||= {}
|
86
89
|
end
|
87
90
|
|
88
|
-
# Validates that the current engine supports Plutonium features.
|
89
|
-
#
|
90
|
-
# @raise [ArgumentError] If the engine doesn't include Plutonium::Pkg::App.
|
91
|
-
# @return [void]
|
92
|
-
def validate_engine!
|
93
|
-
raise ArgumentError, "#{engine} must include Plutonium::Pkg::App to register resources" unless supported_engine?
|
94
|
-
end
|
95
|
-
|
96
|
-
# Checks if the current engine supports Plutonium features.
|
97
|
-
#
|
98
|
-
# @return [Boolean] True if the engine includes Plutonium::Pkg::App, false otherwise.
|
99
|
-
def supported_engine?
|
100
|
-
engine.include?(Plutonium::Pkg::App)
|
101
|
-
end
|
102
|
-
|
103
91
|
# Determines the appropriate engine based on the current scope.
|
104
92
|
#
|
105
93
|
# @return [Class] The determined engine class.
|
@@ -0,0 +1,125 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Plutonium
|
4
|
+
module UI
|
5
|
+
class ActionButton < Plutonium::UI::Component::Base
|
6
|
+
include Phlex::Rails::Helpers::LinkTo
|
7
|
+
include Phlex::Rails::Helpers::ButtonTo
|
8
|
+
|
9
|
+
def initialize(action, url:, variant: :default)
|
10
|
+
@action = action
|
11
|
+
@url = url
|
12
|
+
@variant = variant
|
13
|
+
end
|
14
|
+
|
15
|
+
def view_template
|
16
|
+
if @action.route_options.method == :get
|
17
|
+
render_link
|
18
|
+
else
|
19
|
+
render_button
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def render_link
|
26
|
+
link_to(
|
27
|
+
@url,
|
28
|
+
class: button_classes,
|
29
|
+
data: {turbo_frame: @action.turbo_frame}
|
30
|
+
) do
|
31
|
+
render_button_content
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def render_button
|
36
|
+
button_to(
|
37
|
+
@url,
|
38
|
+
method: @action.route_options.method,
|
39
|
+
name: :return_to, value: request.original_url,
|
40
|
+
class: "inline-block",
|
41
|
+
form: {
|
42
|
+
data: {
|
43
|
+
turbo_confirm: @action.confirmation,
|
44
|
+
turbo_frame: @action.turbo_frame
|
45
|
+
}
|
46
|
+
}
|
47
|
+
) do
|
48
|
+
span(class: button_classes) do
|
49
|
+
render_button_content
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def render_button_content
|
55
|
+
if @action.icon
|
56
|
+
render @action.icon.new(class: icon_classes)
|
57
|
+
end
|
58
|
+
span { @action.label } unless @variant == :table
|
59
|
+
end
|
60
|
+
|
61
|
+
def button_classes
|
62
|
+
tokens(
|
63
|
+
base_classes,
|
64
|
+
color_classes,
|
65
|
+
size_classes,
|
66
|
+
-> { @action.icon && @variant != :table } => "space-x-1"
|
67
|
+
)
|
68
|
+
end
|
69
|
+
|
70
|
+
def base_classes
|
71
|
+
if @variant == :table
|
72
|
+
"inline-flex items-center justify-center p-1 rounded-lg focus:outline-none focus:ring-2"
|
73
|
+
else
|
74
|
+
"flex items-center justify-center px-4 py-2 text-sm font-medium rounded-lg focus:outline-none focus:ring-4"
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def icon_classes
|
79
|
+
if @variant == :table
|
80
|
+
"h-4 w-4"
|
81
|
+
else
|
82
|
+
"h-3.5 w-3.5 mr-2 -ml-1"
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def size_classes
|
87
|
+
(@variant == :table) ? "text-xs" : "text-sm"
|
88
|
+
end
|
89
|
+
|
90
|
+
def color_classes
|
91
|
+
case @action.color || @action.category.to_sym
|
92
|
+
when :primary
|
93
|
+
table_variant_class(
|
94
|
+
"bg-primary-100 text-primary-700 hover:bg-primary-200 focus:ring-primary-300 dark:bg-primary-700 dark:text-primary-100 dark:hover:bg-primary-600 dark:focus:ring-primary-600",
|
95
|
+
"bg-primary-700 text-white hover:bg-primary-800 focus:ring-primary-300 dark:bg-primary-600 dark:hover:bg-primary-700 dark:focus:ring-primary-800"
|
96
|
+
)
|
97
|
+
when :warning
|
98
|
+
table_variant_class(
|
99
|
+
"bg-yellow-100 text-yellow-700 hover:bg-yellow-200 focus:ring-yellow-300 dark:bg-yellow-700 dark:text-yellow-100 dark:hover:bg-yellow-600 dark:focus:ring-yellow-600",
|
100
|
+
"bg-yellow-400 text-white hover:bg-yellow-500 focus:ring-yellow-300 dark:bg-yellow-600 dark:hover:bg-yellow-700 dark:focus:ring-yellow-800"
|
101
|
+
)
|
102
|
+
when :danger
|
103
|
+
table_variant_class(
|
104
|
+
"bg-red-100 text-red-700 hover:bg-red-200 focus:ring-red-300 dark:bg-red-700 dark:text-red-100 dark:hover:bg-red-600 dark:focus:ring-red-600",
|
105
|
+
"bg-red-700 text-white hover:bg-red-800 focus:ring-red-300 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-900"
|
106
|
+
)
|
107
|
+
when :success
|
108
|
+
table_variant_class(
|
109
|
+
"bg-green-100 text-green-700 hover:bg-green-200 focus:ring-green-300 dark:bg-green-700 dark:text-green-100 dark:hover:bg-green-600 dark:focus:ring-green-600",
|
110
|
+
"bg-green-700 text-white hover:bg-green-800 focus:ring-green-300 dark:bg-green-600 dark:hover:bg-green-700 dark:focus:ring-green-800"
|
111
|
+
)
|
112
|
+
else
|
113
|
+
table_variant_class(
|
114
|
+
"bg-gray-100 text-gray-700 hover:bg-gray-200 focus:ring-gray-300 dark:bg-gray-700 dark:text-gray-100 dark:hover:bg-gray-600 dark:focus:ring-gray-600",
|
115
|
+
"border border-gray-200 bg-white text-gray-900 hover:bg-gray-100 hover:text-primary-700 focus:z-10 focus:ring-gray-100 dark:border-gray-600 dark:bg-gray-800 dark:text-gray-200 dark:hover:bg-gray-700 dark:hover:text-white dark:focus:ring-gray-700"
|
116
|
+
)
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
def table_variant_class(table_class, default_class)
|
121
|
+
(@variant == :table) ? table_class : default_class
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
125
|
+
end
|
@@ -0,0 +1,163 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module UI
|
3
|
+
class Breadcrumbs < Plutonium::UI::Component::Base
|
4
|
+
include Phlex::Rails::Helpers::ActionName
|
5
|
+
include Phlex::Rails::Helpers::LinkTo
|
6
|
+
|
7
|
+
def view_template
|
8
|
+
nav(
|
9
|
+
class:
|
10
|
+
"flex py-3 text-gray-700 mb-2",
|
11
|
+
aria_label: "Breadcrumb"
|
12
|
+
) do
|
13
|
+
ol(
|
14
|
+
class:
|
15
|
+
"inline-flex items-center space-x-1 md:space-x-2 rtl:space-x-reverse"
|
16
|
+
) do
|
17
|
+
# Dashboard
|
18
|
+
li(class: "inline-flex items-center") do
|
19
|
+
a(
|
20
|
+
href: helpers.root_path,
|
21
|
+
class:
|
22
|
+
"inline-flex items-center text-sm font-medium text-gray-700 hover:text-primary-600 dark:text-gray-200 dark:hover:text-white"
|
23
|
+
) do
|
24
|
+
svg(
|
25
|
+
class: "w-3 h-3 me-2.5",
|
26
|
+
aria_hidden: "true",
|
27
|
+
xmlns: "http://www.w3.org/2000/svg",
|
28
|
+
fill: "currentColor",
|
29
|
+
viewbox: "0 0 20 20"
|
30
|
+
) do |s|
|
31
|
+
s.path(
|
32
|
+
d:
|
33
|
+
"m19.707 9.293-2-2-7-7a1 1 0 0 0-1.414 0l-7 7-2 2a1 1 0 0 0 1.414 1.414L2 10.414V18a2 2 0 0 0 2 2h3a1 1 0 0 0 1-1v-4a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v4a1 1 0 0 0 1 1h3a2 2 0 0 0 2-2v-7.586l.293.293a1 1 0 0 0 1.414-1.414Z"
|
34
|
+
)
|
35
|
+
end
|
36
|
+
plain " Dashboard "
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# Parent
|
41
|
+
if current_parent.present?
|
42
|
+
# Parent Resource
|
43
|
+
li(class: "flex items-center") do
|
44
|
+
svg(
|
45
|
+
class: "rtl:rotate-180 block w-3 h-3 mx-1 text-gray-400",
|
46
|
+
aria_hidden: "true",
|
47
|
+
xmlns: "http://www.w3.org/2000/svg",
|
48
|
+
fill: "none",
|
49
|
+
viewbox: "0 0 6 10"
|
50
|
+
) do |s|
|
51
|
+
s.path(
|
52
|
+
stroke: "currentColor",
|
53
|
+
stroke_linecap: "round",
|
54
|
+
stroke_linejoin: "round",
|
55
|
+
stroke_width: "2",
|
56
|
+
d: "m1 9 4-4-4-4"
|
57
|
+
)
|
58
|
+
end
|
59
|
+
link_to resource_name_plural(current_parent.class),
|
60
|
+
resource_url_for(current_parent.class, parent: nil),
|
61
|
+
class:
|
62
|
+
"ms-1 text-sm font-medium text-gray-700 hover:text-primary-600 md:ms-2 dark:text-gray-200 dark:hover:text-white"
|
63
|
+
end
|
64
|
+
|
65
|
+
# Parent Itself
|
66
|
+
li(class: "flex items-center") do
|
67
|
+
svg(
|
68
|
+
class: "rtl:rotate-180 block w-3 h-3 mx-1 text-gray-400",
|
69
|
+
aria_hidden: "true",
|
70
|
+
xmlns: "http://www.w3.org/2000/svg",
|
71
|
+
fill: "none",
|
72
|
+
viewbox: "0 0 6 10"
|
73
|
+
) do |s|
|
74
|
+
s.path(
|
75
|
+
stroke: "currentColor",
|
76
|
+
stroke_linecap: "round",
|
77
|
+
stroke_linejoin: "round",
|
78
|
+
stroke_width: "2",
|
79
|
+
d: "m1 9 4-4-4-4"
|
80
|
+
)
|
81
|
+
end
|
82
|
+
link_to display_name_of(current_parent),
|
83
|
+
resource_url_for(current_parent, parent: nil),
|
84
|
+
class:
|
85
|
+
"ms-1 text-sm font-medium text-gray-700 hover:text-primary-600 md:ms-2 dark:text-gray-200 dark:hover:text-white"
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
# Record
|
90
|
+
if resource_record.present?
|
91
|
+
# Record Resource
|
92
|
+
li(class: "flex items-center") do
|
93
|
+
svg(
|
94
|
+
class: "rtl:rotate-180 block w-3 h-3 mx-1 text-gray-400",
|
95
|
+
aria_hidden: "true",
|
96
|
+
xmlns: "http://www.w3.org/2000/svg",
|
97
|
+
fill: "none",
|
98
|
+
viewbox: "0 0 6 10"
|
99
|
+
) do |s|
|
100
|
+
s.path(
|
101
|
+
stroke: "currentColor",
|
102
|
+
stroke_linecap: "round",
|
103
|
+
stroke_linejoin: "round",
|
104
|
+
stroke_width: "2",
|
105
|
+
d: "m1 9 4-4-4-4"
|
106
|
+
)
|
107
|
+
end
|
108
|
+
link_to resource_name_plural(resource_class),
|
109
|
+
resource_url_for(resource_class),
|
110
|
+
class:
|
111
|
+
"ms-1 text-sm font-medium text-gray-700 hover:text-primary-600 md:ms-2 dark:text-gray-200 dark:hover:text-white"
|
112
|
+
end
|
113
|
+
|
114
|
+
# Record Itself
|
115
|
+
if resource_record.persisted? && action_name != "show"
|
116
|
+
li(class: "flex items-center") do
|
117
|
+
svg(
|
118
|
+
class: "rtl:rotate-180 block w-3 h-3 mx-1 text-gray-400",
|
119
|
+
aria_hidden: "true",
|
120
|
+
xmlns: "http://www.w3.org/2000/svg",
|
121
|
+
fill: "none",
|
122
|
+
viewbox: "0 0 6 10"
|
123
|
+
) do |s|
|
124
|
+
s.path(
|
125
|
+
stroke: "currentColor",
|
126
|
+
stroke_linecap: "round",
|
127
|
+
stroke_linejoin: "round",
|
128
|
+
stroke_width: "2",
|
129
|
+
d: "m1 9 4-4-4-4"
|
130
|
+
)
|
131
|
+
end
|
132
|
+
link_to display_name_of(resource_record),
|
133
|
+
resource_url_for(resource_record),
|
134
|
+
class:
|
135
|
+
"ms-1 text-sm font-medium text-gray-700 hover:text-primary-600 md:ms-2 dark:text-gray-200 dark:hover:text-white"
|
136
|
+
end
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
# Trailing Caret
|
141
|
+
li(class: "flex items-center") do
|
142
|
+
svg(
|
143
|
+
class: "rtl:rotate-180 block w-3 h-3 mx-1 text-gray-400",
|
144
|
+
aria_hidden: "true",
|
145
|
+
xmlns: "http://www.w3.org/2000/svg",
|
146
|
+
fill: "none",
|
147
|
+
viewbox: "0 0 6 10"
|
148
|
+
) do |s|
|
149
|
+
s.path(
|
150
|
+
stroke: "currentColor",
|
151
|
+
stroke_linecap: "round",
|
152
|
+
stroke_linejoin: "round",
|
153
|
+
stroke_width: "2",
|
154
|
+
d: "m1 9 4-4-4-4"
|
155
|
+
)
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
end
|
163
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "phlex"
|
4
|
+
|
5
|
+
module Plutonium
|
6
|
+
module UI
|
7
|
+
module Component
|
8
|
+
class Base < (defined?(::ApplicationComponent) ? ::ApplicationComponent : Phlex::HTML)
|
9
|
+
include Plutonium::UI::Component::Behaviour
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Plutonium
|
4
|
+
module UI
|
5
|
+
module Component
|
6
|
+
module Behaviour
|
7
|
+
extend ActiveSupport::Concern
|
8
|
+
include Methods
|
9
|
+
include Kit
|
10
|
+
|
11
|
+
if Rails.env.development?
|
12
|
+
def around_template(&)
|
13
|
+
comment { "open:#{self.class.name}" }
|
14
|
+
super
|
15
|
+
comment { "close:#{self.class.name}" }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
def phlexi_render(arg, &)
|
22
|
+
return unless arg
|
23
|
+
raise ArgumentError, "phlexi_render requires a default render block" unless block_given?
|
24
|
+
|
25
|
+
# Handle Phlex components or Rails Renderables
|
26
|
+
if arg.class < Phlex::SGML || arg.respond_to?(:render_in)
|
27
|
+
render arg
|
28
|
+
# Handle procs
|
29
|
+
elsif arg.respond_to?(:to_proc)
|
30
|
+
instance_exec(&arg)
|
31
|
+
else
|
32
|
+
yield
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "phlex"
|
4
|
+
|
5
|
+
module Plutonium
|
6
|
+
module UI
|
7
|
+
module Component
|
8
|
+
module Kit
|
9
|
+
extend ActiveSupport::Concern
|
10
|
+
|
11
|
+
def Breadcrumbs(...) = render Plutonium::UI::Breadcrumbs.new(...)
|
12
|
+
|
13
|
+
def DynaFrameContent(...) = render Plutonium::UI::DynaFrame::Content.new(...)
|
14
|
+
|
15
|
+
def PageHeader(...) = render Plutonium::UI::PageHeader.new(...)
|
16
|
+
|
17
|
+
def ActionButton(...) = render Plutonium::UI::ActionButton.new(...)
|
18
|
+
|
19
|
+
def EmptyCard(...) = render Plutonium::UI::EmptyCard.new(...)
|
20
|
+
|
21
|
+
def TableSearchBar(...) = render Plutonium::UI::Table::Components::SearchBar.new(...)
|
22
|
+
|
23
|
+
def TableScopesBar(...) = render Plutonium::UI::Table::Components::ScopesBar.new(...)
|
24
|
+
|
25
|
+
def TableInfo(...) = render Plutonium::UI::Table::Components::PagyInfo.new(...)
|
26
|
+
|
27
|
+
def TablePagination(...) = render Plutonium::UI::Table::Components::PagyPagination.new(...)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|