plutonium 0.42.0 → 0.43.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.claude/skills/plutonium-controller/SKILL.md +38 -1
- data/.claude/skills/plutonium-definition/SKILL.md +14 -0
- data/.claude/skills/plutonium-forms/SKILL.md +16 -1
- data/.claude/skills/plutonium-profile/SKILL.md +276 -0
- data/.claude/skills/plutonium-views/SKILL.md +23 -1
- data/CHANGELOG.md +36 -0
- data/app/assets/plutonium.css +1 -1
- data/app/views/plutonium/_resource_header.html.erb +6 -27
- data/app/views/plutonium/_resource_sidebar.html.erb +1 -2
- data/app/views/resource/_resource_details.rabl +3 -2
- data/app/views/resource/index.rabl +3 -2
- data/app/views/resource/show.rabl +3 -2
- data/docs/guides/user-profile.md +322 -0
- data/docs/reference/controller/index.md +38 -1
- data/docs/reference/definition/index.md +16 -0
- data/docs/reference/views/forms.md +15 -0
- data/docs/reference/views/index.md +23 -1
- data/gemfiles/rails_7.gemfile.lock +1 -1
- data/gemfiles/rails_8.0.gemfile.lock +1 -1
- data/gemfiles/rails_8.1.gemfile.lock +1 -1
- data/lib/generators/pu/core/assets/assets_generator.rb +12 -0
- data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +11 -0
- data/lib/generators/pu/core/typespec/templates/common.tsp.tt +95 -0
- data/lib/generators/pu/core/typespec/templates/main.tsp.tt +27 -0
- data/lib/generators/pu/core/typespec/templates/main_multi.tsp.tt +25 -0
- data/lib/generators/pu/core/typespec/templates/model.tsp.tt +226 -0
- data/lib/generators/pu/core/typespec/typespec_generator.rb +342 -0
- data/lib/generators/pu/invites/USAGE +0 -1
- data/lib/generators/pu/invites/install_generator.rb +62 -15
- data/lib/generators/pu/invites/templates/db/migrate/create_user_invites.rb.tt +2 -2
- data/lib/generators/pu/invites/templates/packages/invites/app/controllers/invites/user_invitations_controller.rb.tt +2 -0
- data/lib/generators/pu/invites/templates/packages/invites/app/controllers/invites/welcome_controller.rb.tt +1 -0
- data/lib/generators/pu/invites/templates/packages/invites/app/models/invites/user_invite.rb.tt +5 -5
- data/lib/generators/pu/invites/templates/packages/invites/app/views/invites/user_invitations/signup.html.erb.tt +4 -4
- data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +1 -1
- data/lib/generators/pu/lib/plutonium_generators/generator.rb +29 -0
- data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +6 -23
- data/lib/generators/pu/pkg/portal/portal_generator.rb +5 -1
- data/lib/generators/pu/profile/USAGE +59 -0
- data/lib/generators/pu/profile/concerns/profile_arguments.rb +27 -0
- data/lib/generators/pu/profile/conn/USAGE +33 -0
- data/lib/generators/pu/profile/conn_generator.rb +167 -0
- data/lib/generators/pu/profile/install_generator.rb +119 -0
- data/lib/generators/pu/profile/setup/USAGE +42 -0
- data/lib/generators/pu/profile/setup_generator.rb +73 -0
- data/lib/generators/pu/rodauth/account_generator.rb +2 -4
- data/lib/generators/pu/rodauth/install_generator.rb +2 -2
- data/lib/generators/pu/rodauth/templates/app/rodauth/account_rodauth_plugin.rb.tt +3 -0
- data/lib/generators/pu/saas/api_client_generator.rb +0 -2
- data/lib/generators/pu/saas/membership_generator.rb +68 -19
- data/lib/generators/pu/saas/setup_generator.rb +7 -2
- data/lib/generators/pu/saas/user_generator.rb +0 -2
- data/lib/plutonium/auth/rodauth.rb +8 -0
- data/lib/plutonium/core/controller.rb +7 -4
- data/lib/plutonium/core/controllers/authorizable.rb +5 -1
- data/lib/plutonium/definition/base.rb +7 -0
- data/lib/plutonium/helpers/display_helper.rb +6 -0
- data/lib/plutonium/profile/security_section.rb +118 -0
- data/lib/plutonium/resource/controller.rb +17 -7
- data/lib/plutonium/resource/controllers/interactive_actions.rb +11 -25
- data/lib/plutonium/resource/controllers/presentable.rb +46 -3
- data/lib/plutonium/resource/record/associated_with.rb +7 -1
- data/lib/plutonium/routing/mapper_extensions.rb +18 -18
- data/lib/plutonium/routing/route_set_extensions.rb +23 -2
- data/lib/plutonium/ui/breadcrumbs.rb +111 -131
- data/lib/plutonium/ui/dyna_frame/content.rb +12 -2
- data/lib/plutonium/ui/form/resource.rb +26 -19
- data/lib/plutonium/ui/page/base.rb +14 -14
- data/lib/plutonium/ui/table/components/selection_column.rb +6 -2
- data/lib/plutonium/ui/table/resource.rb +3 -2
- data/lib/plutonium/version.rb +1 -1
- data/package.json +1 -1
- metadata +17 -3
- data/lib/generators/pu/rodauth/concerns/gem_helpers.rb +0 -19
|
@@ -12,147 +12,127 @@ module Plutonium
|
|
|
12
12
|
ol(
|
|
13
13
|
class: "inline-flex items-center gap-1 md:gap-2"
|
|
14
14
|
) do
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class: "w-3 h-3 me-2.5",
|
|
23
|
-
aria_hidden: "true",
|
|
24
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
25
|
-
fill: "currentColor",
|
|
26
|
-
viewbox: "0 0 20 20"
|
|
27
|
-
) do |s|
|
|
28
|
-
s.path(
|
|
29
|
-
d:
|
|
30
|
-
"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"
|
|
31
|
-
)
|
|
32
|
-
end
|
|
33
|
-
plain " Dashboard "
|
|
34
|
-
end
|
|
35
|
-
end
|
|
15
|
+
render_dashboard_link
|
|
16
|
+
render_parent_breadcrumbs if current_parent.present?
|
|
17
|
+
render_resource_breadcrumbs if resource_record?
|
|
18
|
+
render_trailing_separator
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
36
22
|
|
|
37
|
-
|
|
38
|
-
if current_parent.present?
|
|
39
|
-
# Parent Resource
|
|
40
|
-
li(class: "flex items-center") do
|
|
41
|
-
svg(
|
|
42
|
-
class: "rtl:rotate-180 block w-3 h-3 mx-1 text-[var(--pu-text-subtle)]",
|
|
43
|
-
aria_hidden: "true",
|
|
44
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
45
|
-
fill: "none",
|
|
46
|
-
viewbox: "0 0 6 10"
|
|
47
|
-
) do |s|
|
|
48
|
-
s.path(
|
|
49
|
-
stroke: "currentColor",
|
|
50
|
-
stroke_linecap: "round",
|
|
51
|
-
stroke_linejoin: "round",
|
|
52
|
-
stroke_width: "2",
|
|
53
|
-
d: "m1 9 4-4-4-4"
|
|
54
|
-
)
|
|
55
|
-
end
|
|
56
|
-
link_to resource_name_plural(current_parent.class),
|
|
57
|
-
resource_url_for(current_parent.class, parent: nil),
|
|
58
|
-
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
59
|
-
end
|
|
23
|
+
private
|
|
60
24
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
link_to display_name_of(current_parent),
|
|
79
|
-
resource_url_for(current_parent, parent: nil),
|
|
80
|
-
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
81
|
-
end
|
|
25
|
+
def render_dashboard_link
|
|
26
|
+
li(class: "inline-flex items-center") do
|
|
27
|
+
a(
|
|
28
|
+
href: root_path,
|
|
29
|
+
class: "inline-flex items-center text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 transition-colors"
|
|
30
|
+
) do
|
|
31
|
+
svg(
|
|
32
|
+
class: "w-3 h-3 me-2.5",
|
|
33
|
+
aria_hidden: "true",
|
|
34
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
35
|
+
fill: "currentColor",
|
|
36
|
+
viewbox: "0 0 20 20"
|
|
37
|
+
) do |s|
|
|
38
|
+
s.path(
|
|
39
|
+
d:
|
|
40
|
+
"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"
|
|
41
|
+
)
|
|
82
42
|
end
|
|
43
|
+
plain " Dashboard "
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
end
|
|
83
47
|
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
aria_hidden: "true",
|
|
92
|
-
xmlns: "http://www.w3.org/2000/svg",
|
|
93
|
-
fill: "none",
|
|
94
|
-
viewbox: "0 0 6 10"
|
|
95
|
-
) do |s|
|
|
96
|
-
s.path(
|
|
97
|
-
stroke: "currentColor",
|
|
98
|
-
stroke_linecap: "round",
|
|
99
|
-
stroke_linejoin: "round",
|
|
100
|
-
stroke_width: "2",
|
|
101
|
-
d: "m1 9 4-4-4-4"
|
|
102
|
-
)
|
|
103
|
-
end
|
|
104
|
-
link_to nestable_resource_name_plural(resource_class),
|
|
105
|
-
resource_url_for(resource_class),
|
|
106
|
-
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
107
|
-
end
|
|
108
|
-
end
|
|
48
|
+
def render_parent_breadcrumbs
|
|
49
|
+
# Parent Resource
|
|
50
|
+
render_breadcrumb_item do
|
|
51
|
+
link_to resource_name_plural(current_parent.class),
|
|
52
|
+
resource_url_for(current_parent.class, parent: nil),
|
|
53
|
+
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
54
|
+
end
|
|
109
55
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
end
|
|
128
|
-
link_to display_name_of(resource_record!),
|
|
129
|
-
resource_url_for(resource_record!),
|
|
130
|
-
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
131
|
-
end
|
|
132
|
-
end
|
|
133
|
-
end
|
|
56
|
+
# Parent Itself
|
|
57
|
+
render_breadcrumb_item do
|
|
58
|
+
link_to display_name_of(current_parent),
|
|
59
|
+
resource_url_for(current_parent, parent: nil),
|
|
60
|
+
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def render_resource_breadcrumbs
|
|
65
|
+
is_singular_route = current_engine.routes.resource_route_config_lookup[resource_class.model_name.plural][:route_type] == :resource
|
|
66
|
+
|
|
67
|
+
if is_singular_route
|
|
68
|
+
render_singular_resource_breadcrumb
|
|
69
|
+
else
|
|
70
|
+
render_plural_resource_breadcrumbs
|
|
71
|
+
end
|
|
72
|
+
end
|
|
134
73
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
)
|
|
144
|
-
s.path(
|
|
145
|
-
stroke: "currentColor",
|
|
146
|
-
stroke_linecap: "round",
|
|
147
|
-
stroke_linejoin: "round",
|
|
148
|
-
stroke_width: "2",
|
|
149
|
-
d: "m1 9 4-4-4-4"
|
|
150
|
-
)
|
|
151
|
-
end
|
|
74
|
+
def render_singular_resource_breadcrumb
|
|
75
|
+
render_breadcrumb_item do
|
|
76
|
+
if resource_record!.persisted? && action_name != "show"
|
|
77
|
+
link_to resource_name(resource_class),
|
|
78
|
+
resource_url_for(resource_record!),
|
|
79
|
+
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
80
|
+
else
|
|
81
|
+
span(class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] md:ms-2") do
|
|
82
|
+
plain resource_name(resource_class)
|
|
152
83
|
end
|
|
153
84
|
end
|
|
154
85
|
end
|
|
155
86
|
end
|
|
87
|
+
|
|
88
|
+
def render_plural_resource_breadcrumbs
|
|
89
|
+
# Resource index link
|
|
90
|
+
render_breadcrumb_item do
|
|
91
|
+
link_to nestable_resource_name_plural(resource_class),
|
|
92
|
+
resource_url_for(resource_class),
|
|
93
|
+
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# Record itself (for non-singular routes only)
|
|
97
|
+
return unless resource_record!.persisted? && action_name != "show"
|
|
98
|
+
|
|
99
|
+
render_breadcrumb_item do
|
|
100
|
+
link_to display_name_of(resource_record!),
|
|
101
|
+
resource_url_for(resource_record!),
|
|
102
|
+
class: "ms-1 text-sm font-medium text-[var(--pu-text-muted)] hover:text-primary-600 md:ms-2 transition-colors"
|
|
103
|
+
end
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def render_trailing_separator
|
|
107
|
+
li(class: "flex items-center") do
|
|
108
|
+
render_chevron_separator
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def render_breadcrumb_item(&)
|
|
113
|
+
li(class: "flex items-center") do
|
|
114
|
+
render_chevron_separator
|
|
115
|
+
yield
|
|
116
|
+
end
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def render_chevron_separator
|
|
120
|
+
svg(
|
|
121
|
+
class: "rtl:rotate-180 block w-3 h-3 mx-1 text-[var(--pu-text-subtle)]",
|
|
122
|
+
aria_hidden: "true",
|
|
123
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
124
|
+
fill: "none",
|
|
125
|
+
viewbox: "0 0 6 10"
|
|
126
|
+
) do |s|
|
|
127
|
+
s.path(
|
|
128
|
+
stroke: "currentColor",
|
|
129
|
+
stroke_linecap: "round",
|
|
130
|
+
stroke_linejoin: "round",
|
|
131
|
+
stroke_width: "2",
|
|
132
|
+
d: "m1 9 4-4-4-4"
|
|
133
|
+
)
|
|
134
|
+
end
|
|
135
|
+
end
|
|
156
136
|
end
|
|
157
137
|
end
|
|
158
138
|
end
|
|
@@ -4,16 +4,26 @@ module Plutonium
|
|
|
4
4
|
class Content < Plutonium::UI::Component::Base
|
|
5
5
|
include Phlex::Rails::Helpers::TurboFrameTag
|
|
6
6
|
|
|
7
|
+
def initialize(content = nil)
|
|
8
|
+
@content = content
|
|
9
|
+
end
|
|
10
|
+
|
|
7
11
|
def view_template
|
|
8
12
|
if current_turbo_frame.present?
|
|
13
|
+
# Frame request: render only the turbo-frame with content
|
|
9
14
|
turbo_frame_tag(current_turbo_frame) do
|
|
10
15
|
render partial("flash")
|
|
11
|
-
|
|
16
|
+
@content&.call
|
|
12
17
|
end
|
|
13
18
|
else
|
|
14
|
-
yield
|
|
19
|
+
# Regular request: yield self so caller can call frame.render_content
|
|
20
|
+
yield(self)
|
|
15
21
|
end
|
|
16
22
|
end
|
|
23
|
+
|
|
24
|
+
def render_content
|
|
25
|
+
@content&.call
|
|
26
|
+
end
|
|
17
27
|
end
|
|
18
28
|
end
|
|
19
29
|
end
|
|
@@ -6,14 +6,15 @@ module Plutonium
|
|
|
6
6
|
class Resource < Base
|
|
7
7
|
include Plutonium::UI::Form::Concerns::RendersNestedResourceFields
|
|
8
8
|
|
|
9
|
-
attr_reader :resource_fields, :resource_definition
|
|
9
|
+
attr_reader :resource_fields, :resource_definition, :singular_resource
|
|
10
10
|
|
|
11
11
|
alias_method :record, :object
|
|
12
12
|
|
|
13
|
-
def initialize(*, resource_fields:, resource_definition:, **, &)
|
|
13
|
+
def initialize(*, resource_fields:, resource_definition:, singular_resource: false, **, &)
|
|
14
14
|
super(*, **, &)
|
|
15
15
|
@resource_fields = resource_fields
|
|
16
16
|
@resource_definition = resource_definition
|
|
17
|
+
@singular_resource = singular_resource
|
|
17
18
|
end
|
|
18
19
|
|
|
19
20
|
def form_template
|
|
@@ -35,28 +36,34 @@ module Plutonium
|
|
|
35
36
|
input name: "return_to", value: request.params[:return_to], type: :hidden, hidden: true
|
|
36
37
|
|
|
37
38
|
actions_wrapper {
|
|
38
|
-
if
|
|
39
|
-
if object.new_record?
|
|
40
|
-
button(
|
|
41
|
-
type: :submit,
|
|
42
|
-
name: "return_to",
|
|
43
|
-
value: request.url,
|
|
44
|
-
class: "px-4 py-2 bg-secondary-600 text-white rounded-md hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-secondary-500"
|
|
45
|
-
) { "Create and add another" }
|
|
46
|
-
else
|
|
47
|
-
button(
|
|
48
|
-
type: :submit,
|
|
49
|
-
name: "return_to",
|
|
50
|
-
value: request.url,
|
|
51
|
-
class: "px-4 py-2 bg-secondary-600 text-white rounded-md hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-secondary-500"
|
|
52
|
-
) { "Update and continue editing" }
|
|
53
|
-
end
|
|
54
|
-
end
|
|
39
|
+
render_submit_and_continue_button if show_submit_and_continue?
|
|
55
40
|
|
|
56
41
|
render submit_button
|
|
57
42
|
}
|
|
58
43
|
end
|
|
59
44
|
|
|
45
|
+
def show_submit_and_continue?
|
|
46
|
+
return false unless object.respond_to?(:new_record?)
|
|
47
|
+
|
|
48
|
+
# Check explicit configuration first
|
|
49
|
+
configured = resource_definition.submit_and_continue
|
|
50
|
+
return configured unless configured.nil?
|
|
51
|
+
|
|
52
|
+
# Auto-detect: hide for singular resources
|
|
53
|
+
!singular_resource
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def render_submit_and_continue_button
|
|
57
|
+
label = object.new_record? ? "Create and add another" : "Update and continue editing"
|
|
58
|
+
|
|
59
|
+
button(
|
|
60
|
+
type: :submit,
|
|
61
|
+
name: "return_to",
|
|
62
|
+
value: request.url,
|
|
63
|
+
class: "px-4 py-2 bg-secondary-600 text-white rounded-md hover:bg-secondary-700 focus:outline-none focus:ring-2 focus:ring-secondary-500"
|
|
64
|
+
) { label }
|
|
65
|
+
end
|
|
66
|
+
|
|
60
67
|
def form_action
|
|
61
68
|
return @form_action unless object.present? && @form_action != false && view_context.present?
|
|
62
69
|
|
|
@@ -10,18 +10,20 @@ module Plutonium
|
|
|
10
10
|
@page_actions = page_actions
|
|
11
11
|
end
|
|
12
12
|
|
|
13
|
-
def view_template(&)
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
13
|
+
def view_template(&block)
|
|
14
|
+
DynaFrameContent(page_content(block)) do |frame|
|
|
15
|
+
render_before_header
|
|
16
|
+
render_header
|
|
17
|
+
render_after_header
|
|
17
18
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
render_before_content
|
|
20
|
+
frame.render_content
|
|
21
|
+
render_after_content
|
|
21
22
|
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
23
|
+
render_before_footer
|
|
24
|
+
render_footer
|
|
25
|
+
render_after_footer
|
|
26
|
+
end
|
|
25
27
|
end
|
|
26
28
|
|
|
27
29
|
private
|
|
@@ -64,10 +66,8 @@ module Plutonium
|
|
|
64
66
|
# Implement toolbar content
|
|
65
67
|
end
|
|
66
68
|
|
|
67
|
-
def
|
|
68
|
-
block
|
|
69
|
-
|
|
70
|
-
DynaFrameContent(&block)
|
|
69
|
+
def page_content(block)
|
|
70
|
+
block || proc { render_default_content }
|
|
71
71
|
end
|
|
72
72
|
|
|
73
73
|
def render_default_content
|
|
@@ -12,7 +12,7 @@ module Plutonium
|
|
|
12
12
|
|
|
13
13
|
def data_cell(wrapped_object)
|
|
14
14
|
allowed_actions = compute_allowed_actions(wrapped_object.unwrapped)
|
|
15
|
-
SelectionDataCell.new(wrapped_object.field(
|
|
15
|
+
SelectionDataCell.new(wrapped_object.field(value_key).dom.value, allowed_actions)
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
# Add hidden class and Stimulus target to header cell
|
|
@@ -34,6 +34,10 @@ module Plutonium
|
|
|
34
34
|
|
|
35
35
|
private
|
|
36
36
|
|
|
37
|
+
def value_key
|
|
38
|
+
options[:value_key] || sample.class.primary_key.to_sym
|
|
39
|
+
end
|
|
40
|
+
|
|
37
41
|
def bulk_actions
|
|
38
42
|
options[:bulk_actions] || []
|
|
39
43
|
end
|
|
@@ -43,7 +47,7 @@ module Plutonium
|
|
|
43
47
|
end
|
|
44
48
|
|
|
45
49
|
def compute_allowed_actions(record)
|
|
46
|
-
return
|
|
50
|
+
return bulk_actions.map { |a| a.name.to_s } unless policy_resolver
|
|
47
51
|
|
|
48
52
|
policy = policy_resolver.call(record)
|
|
49
53
|
bulk_actions.select { |action|
|
|
@@ -49,8 +49,9 @@ module Plutonium
|
|
|
49
49
|
|
|
50
50
|
render Plutonium::UI::Table::Base.new(collection) do |table|
|
|
51
51
|
# Selection column for bulk actions (hidden by default, Stimulus shows it)
|
|
52
|
-
#
|
|
53
|
-
|
|
52
|
+
# Use :_selection as column key to avoid conflicts with field columns
|
|
53
|
+
# value_key defaults to model's primary_key
|
|
54
|
+
table.selection_column :_selection,
|
|
54
55
|
bulk_actions:,
|
|
55
56
|
policy_resolver: ->(record) { policy_for(record:) }
|
|
56
57
|
|
data/lib/plutonium/version.rb
CHANGED
data/package.json
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: plutonium
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.43.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Stefan Froelich
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-
|
|
11
|
+
date: 2026-03-05 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: zeitwerk
|
|
@@ -418,6 +418,7 @@ files:
|
|
|
418
418
|
- ".claude/skills/plutonium-package/SKILL.md"
|
|
419
419
|
- ".claude/skills/plutonium-policy/SKILL.md"
|
|
420
420
|
- ".claude/skills/plutonium-portal/SKILL.md"
|
|
421
|
+
- ".claude/skills/plutonium-profile/SKILL.md"
|
|
421
422
|
- ".claude/skills/plutonium-resource/SKILL.md"
|
|
422
423
|
- ".claude/skills/plutonium-rodauth/SKILL.md"
|
|
423
424
|
- ".claude/skills/plutonium-theming/SKILL.md"
|
|
@@ -543,6 +544,7 @@ files:
|
|
|
543
544
|
- docs/guides/theming.md
|
|
544
545
|
- docs/guides/troubleshooting.md
|
|
545
546
|
- docs/guides/user-invites.md
|
|
547
|
+
- docs/guides/user-profile.md
|
|
546
548
|
- docs/index.md
|
|
547
549
|
- docs/og-image.html
|
|
548
550
|
- docs/public/android-chrome-192x192.png
|
|
@@ -609,6 +611,11 @@ files:
|
|
|
609
611
|
- lib/generators/pu/core/install/templates/config/packages.rb
|
|
610
612
|
- lib/generators/pu/core/ruby/ruby_generator.rb
|
|
611
613
|
- lib/generators/pu/core/ruby/templates/.keep
|
|
614
|
+
- lib/generators/pu/core/typespec/templates/common.tsp.tt
|
|
615
|
+
- lib/generators/pu/core/typespec/templates/main.tsp.tt
|
|
616
|
+
- lib/generators/pu/core/typespec/templates/main_multi.tsp.tt
|
|
617
|
+
- lib/generators/pu/core/typespec/templates/model.tsp.tt
|
|
618
|
+
- lib/generators/pu/core/typespec/typespec_generator.rb
|
|
612
619
|
- lib/generators/pu/core/update/update_generator.rb
|
|
613
620
|
- lib/generators/pu/docker/install/install_generator.rb
|
|
614
621
|
- lib/generators/pu/docker/install/templates/.keep
|
|
@@ -719,6 +726,13 @@ files:
|
|
|
719
726
|
- lib/generators/pu/pkg/portal/templates/app/views/package/dashboard/index.html.erb
|
|
720
727
|
- lib/generators/pu/pkg/portal/templates/config/routes.rb.tt
|
|
721
728
|
- lib/generators/pu/pkg/portal/templates/lib/engine.rb.tt
|
|
729
|
+
- lib/generators/pu/profile/USAGE
|
|
730
|
+
- lib/generators/pu/profile/concerns/profile_arguments.rb
|
|
731
|
+
- lib/generators/pu/profile/conn/USAGE
|
|
732
|
+
- lib/generators/pu/profile/conn_generator.rb
|
|
733
|
+
- lib/generators/pu/profile/install_generator.rb
|
|
734
|
+
- lib/generators/pu/profile/setup/USAGE
|
|
735
|
+
- lib/generators/pu/profile/setup_generator.rb
|
|
722
736
|
- lib/generators/pu/res/conn/USAGE
|
|
723
737
|
- lib/generators/pu/res/conn/conn_generator.rb
|
|
724
738
|
- lib/generators/pu/res/conn/templates/.keep
|
|
@@ -745,7 +759,6 @@ files:
|
|
|
745
759
|
- lib/generators/pu/rodauth/concerns/account_selector.rb
|
|
746
760
|
- lib/generators/pu/rodauth/concerns/configuration.rb
|
|
747
761
|
- lib/generators/pu/rodauth/concerns/feature_selector.rb
|
|
748
|
-
- lib/generators/pu/rodauth/concerns/gem_helpers.rb
|
|
749
762
|
- lib/generators/pu/rodauth/install_generator.rb
|
|
750
763
|
- lib/generators/pu/rodauth/migration/active_record/account_expiration.erb
|
|
751
764
|
- lib/generators/pu/rodauth/migration/active_record/active_sessions.erb
|
|
@@ -896,6 +909,7 @@ files:
|
|
|
896
909
|
- lib/plutonium/portal/controller.rb
|
|
897
910
|
- lib/plutonium/portal/dynamic_controllers.rb
|
|
898
911
|
- lib/plutonium/portal/engine.rb
|
|
912
|
+
- lib/plutonium/profile/security_section.rb
|
|
899
913
|
- lib/plutonium/query/adhoc_block.rb
|
|
900
914
|
- lib/plutonium/query/base.rb
|
|
901
915
|
- lib/plutonium/query/filter.rb
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Pu
|
|
4
|
-
module Rodauth
|
|
5
|
-
module Concerns
|
|
6
|
-
module GemHelpers
|
|
7
|
-
private
|
|
8
|
-
|
|
9
|
-
def gem_in_bundle?(name)
|
|
10
|
-
in_root do
|
|
11
|
-
return true if File.exist?("Gemfile") && File.read("Gemfile").match?(/gem ['"]#{name}['"]/)
|
|
12
|
-
return true if File.exist?("Gemfile.lock") && File.read("Gemfile.lock").include?(" #{name} ")
|
|
13
|
-
end
|
|
14
|
-
false
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|