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
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: c6775aec4947b991b03ae8a90d29761106765bf7a960153b938298d366a5c5b0
|
|
4
|
+
data.tar.gz: bc7efa2d03feaa76610d747a182c9bf4e045c55a0af8ea21b743390b19061b5e
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3e5686e8560df32a8913be75ac08d7ce0df8543810982322843435c55dd1606b0412f619732613fa55c9252867b3a6f3553fd4d0ff10f08633b9c7bfb519cad2
|
|
7
|
+
data.tar.gz: 205ee9f10dbffd3e0437b48aa04b1c9f61d0ab6ee67ee208e084f318021b0816fbc01b1b143a455a02a907cbb5e246b0ac25ec5e7dd75c7e08ebfcce5dc4fc31
|
|
@@ -265,9 +265,46 @@ end
|
|
|
265
265
|
|
|
266
266
|
Controllers automatically:
|
|
267
267
|
- Scope all queries to the entity
|
|
268
|
-
- Exclude entity field from forms
|
|
268
|
+
- Exclude entity field from forms (detected by association class)
|
|
269
|
+
- Inject entity value on create/update
|
|
269
270
|
- Provide `current_scoped_entity` method
|
|
270
271
|
|
|
272
|
+
### Association Detection
|
|
273
|
+
|
|
274
|
+
Plutonium auto-detects which `belongs_to` association points to the scoped entity class. This works even when `param_key` differs from the association name:
|
|
275
|
+
|
|
276
|
+
```ruby
|
|
277
|
+
# Portal config
|
|
278
|
+
scope_to_entity Competition::Team, param_key: :team
|
|
279
|
+
|
|
280
|
+
# Model (association name differs from param_key)
|
|
281
|
+
class Match < ApplicationRecord
|
|
282
|
+
belongs_to :competition_team # Plutonium finds this by class
|
|
283
|
+
end
|
|
284
|
+
```
|
|
285
|
+
|
|
286
|
+
### Multiple Associations to Same Class
|
|
287
|
+
|
|
288
|
+
If a model has multiple associations to the scoped entity class, Plutonium raises an error:
|
|
289
|
+
|
|
290
|
+
```
|
|
291
|
+
Match has multiple associations to Competition::Team: home_team, away_team.
|
|
292
|
+
Plutonium cannot auto-detect which one to use for entity scoping.
|
|
293
|
+
Override `scoped_entity_association` in your controller to specify the association.
|
|
294
|
+
```
|
|
295
|
+
|
|
296
|
+
Resolve by overriding `scoped_entity_association`:
|
|
297
|
+
|
|
298
|
+
```ruby
|
|
299
|
+
class MatchesController < ::ResourceController
|
|
300
|
+
private
|
|
301
|
+
|
|
302
|
+
def scoped_entity_association
|
|
303
|
+
:home_team # Return the association name as a symbol
|
|
304
|
+
end
|
|
305
|
+
end
|
|
306
|
+
```
|
|
307
|
+
|
|
271
308
|
## Authorization Verification
|
|
272
309
|
|
|
273
310
|
Controllers verify authorization was performed:
|
|
@@ -170,6 +170,20 @@ end
|
|
|
170
170
|
| `input` blocks | Yes | Yes | Yes |
|
|
171
171
|
| Page title procs | Yes | Yes (current_record!) | Yes |
|
|
172
172
|
|
|
173
|
+
## Form Configuration
|
|
174
|
+
|
|
175
|
+
```ruby
|
|
176
|
+
class PostDefinition < ResourceDefinition
|
|
177
|
+
# Controls "Save and add another" / "Update and continue editing" buttons
|
|
178
|
+
# nil (default) = auto-detect (hidden for singular resources, shown for plural)
|
|
179
|
+
# true = always show
|
|
180
|
+
# false = always hide
|
|
181
|
+
submit_and_continue false
|
|
182
|
+
end
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
Singular resources (e.g., `resource :profile` routes or `has_one` nested) auto-hide this button since creating "another" doesn't make sense.
|
|
186
|
+
|
|
173
187
|
## Page Customization
|
|
174
188
|
|
|
175
189
|
```ruby
|
|
@@ -327,12 +327,27 @@ end
|
|
|
327
327
|
|
|
328
328
|
## Form Actions
|
|
329
329
|
|
|
330
|
+
### Submit and Continue Button
|
|
331
|
+
|
|
332
|
+
Forms include a secondary button ("Create and add another" for new records, "Update and continue editing" for existing). Control this in your definition:
|
|
333
|
+
|
|
334
|
+
```ruby
|
|
335
|
+
class PostDefinition < ResourceDefinition
|
|
336
|
+
# nil (default) = auto-detect (hidden for singular resources, shown for plural)
|
|
337
|
+
# true = always show
|
|
338
|
+
# false = always hide
|
|
339
|
+
submit_and_continue false
|
|
340
|
+
end
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
Singular resources (e.g., `resource :profile` routes or `has_one` nested) auto-hide this button.
|
|
344
|
+
|
|
330
345
|
### Default Actions
|
|
331
346
|
|
|
332
347
|
```ruby
|
|
333
348
|
def render_actions
|
|
334
349
|
actions_wrapper {
|
|
335
|
-
# "Create and add another" / "Update and continue editing" button
|
|
350
|
+
# "Create and add another" / "Update and continue editing" button (if enabled)
|
|
336
351
|
# Primary submit button
|
|
337
352
|
render submit_button
|
|
338
353
|
}
|
|
@@ -0,0 +1,276 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: plutonium-profile
|
|
3
|
+
description: Plutonium user profile - account settings page with Rodauth security links
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Plutonium User Profile
|
|
7
|
+
|
|
8
|
+
Plutonium provides a Profile resource generator for managing Rodauth account settings. The profile resource allows users to:
|
|
9
|
+
- View and edit their profile information
|
|
10
|
+
- Access Rodauth security features (change password, 2FA, etc.)
|
|
11
|
+
- Manage their account settings in one place
|
|
12
|
+
|
|
13
|
+
## Quick Setup
|
|
14
|
+
|
|
15
|
+
Use the setup generator to create and connect the profile in one command:
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
rails g pu:profile:setup date_of_birth:date bio:text \
|
|
19
|
+
--dest=competition \
|
|
20
|
+
--portal=competition_portal
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
## Step-by-Step Installation
|
|
24
|
+
|
|
25
|
+
### Install the Profile Resource
|
|
26
|
+
|
|
27
|
+
```bash
|
|
28
|
+
rails generate pu:profile:install --dest=main_app
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
**Options:**
|
|
32
|
+
|
|
33
|
+
| Option | Default | Description |
|
|
34
|
+
|--------|---------|-------------|
|
|
35
|
+
| `--dest=DESTINATION` | (prompts) | Target package or main_app |
|
|
36
|
+
| `--user-model=NAME` | User | Rodauth user model name |
|
|
37
|
+
|
|
38
|
+
**With custom fields:**
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
rails g pu:profile:install \
|
|
42
|
+
bio:text \
|
|
43
|
+
avatar:attachment \
|
|
44
|
+
'timezone:string?' \
|
|
45
|
+
--dest=customer
|
|
46
|
+
```
|
|
47
|
+
|
|
48
|
+
**With custom name:**
|
|
49
|
+
|
|
50
|
+
```bash
|
|
51
|
+
rails g pu:profile:install AccountSettings \
|
|
52
|
+
bio:text \
|
|
53
|
+
--dest=main_app
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
## What Gets Created
|
|
57
|
+
|
|
58
|
+
The generator creates a standard Plutonium resource:
|
|
59
|
+
|
|
60
|
+
```
|
|
61
|
+
app/models/[package/]profile.rb # Profile model
|
|
62
|
+
db/migrate/xxx_create_profiles.rb # Migration
|
|
63
|
+
app/controllers/[package/]profiles_controller.rb
|
|
64
|
+
app/policies/[package/]profile_policy.rb
|
|
65
|
+
app/definitions/[package/]profile_definition.rb
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
And modifies:
|
|
69
|
+
- **User model**: Adds `has_one :profile, dependent: :destroy`
|
|
70
|
+
- **Definition**: Injects custom ShowPage with SecuritySection
|
|
71
|
+
|
|
72
|
+
## The SecuritySection Component
|
|
73
|
+
|
|
74
|
+
The generator injects a custom `ShowPage` that renders `Plutonium::Profile::SecuritySection`:
|
|
75
|
+
|
|
76
|
+
```ruby
|
|
77
|
+
class ProfileDefinition < Plutonium::Resource::Definition
|
|
78
|
+
class ShowPage < ShowPage
|
|
79
|
+
private
|
|
80
|
+
|
|
81
|
+
def render_after_content
|
|
82
|
+
render Plutonium::Profile::SecuritySection.new
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
The `SecuritySection` component dynamically checks which Rodauth features are enabled and displays links for:
|
|
89
|
+
|
|
90
|
+
| Feature | Label | Description |
|
|
91
|
+
|---------|-------|-------------|
|
|
92
|
+
| `change_password` | Change Password | Update account password |
|
|
93
|
+
| `change_login` | Change Email | Update email address |
|
|
94
|
+
| `otp` | Two-Factor Authentication | Set up TOTP |
|
|
95
|
+
| `recovery_codes` | Recovery Codes | View/regenerate backup codes |
|
|
96
|
+
| `webauthn` | Security Keys | Manage passkeys |
|
|
97
|
+
| `active_sessions` | Active Sessions | View/manage sessions |
|
|
98
|
+
| `close_account` | Close Account | Delete account |
|
|
99
|
+
|
|
100
|
+
Only enabled Rodauth features are displayed.
|
|
101
|
+
|
|
102
|
+
## After Generation
|
|
103
|
+
|
|
104
|
+
### 1. Run Migrations
|
|
105
|
+
|
|
106
|
+
```bash
|
|
107
|
+
rails db:migrate
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### 2. Connect to Portal
|
|
111
|
+
|
|
112
|
+
Use the profile connect generator to register as a singular resource and configure the `profile_url` helper:
|
|
113
|
+
|
|
114
|
+
```bash
|
|
115
|
+
rails g pu:profile:conn --dest=customer_portal
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
This:
|
|
119
|
+
- Registers the Profile as a singular resource (`/profile` instead of `/profiles/:id`)
|
|
120
|
+
- Adds `profile_url` helper to enable the "Profile" link in the user menu
|
|
121
|
+
|
|
122
|
+
### 3. Create Profile Automatically
|
|
123
|
+
|
|
124
|
+
Users need a profile created. Add a callback or use `find_or_create`:
|
|
125
|
+
|
|
126
|
+
```ruby
|
|
127
|
+
# Option A: Callback on User
|
|
128
|
+
class User < ApplicationRecord
|
|
129
|
+
after_create :create_profile!
|
|
130
|
+
|
|
131
|
+
private
|
|
132
|
+
|
|
133
|
+
def create_profile!
|
|
134
|
+
create_profile
|
|
135
|
+
end
|
|
136
|
+
end
|
|
137
|
+
|
|
138
|
+
# Option B: In controller or before_action
|
|
139
|
+
def current_profile
|
|
140
|
+
@current_profile ||= current_user.profile || current_user.create_profile
|
|
141
|
+
end
|
|
142
|
+
```
|
|
143
|
+
|
|
144
|
+
## Customization
|
|
145
|
+
|
|
146
|
+
### Adding Profile Fields
|
|
147
|
+
|
|
148
|
+
Add fields during generation:
|
|
149
|
+
|
|
150
|
+
```bash
|
|
151
|
+
rails g pu:profile:install \
|
|
152
|
+
bio:text \
|
|
153
|
+
avatar:attachment \
|
|
154
|
+
website:string \
|
|
155
|
+
'company:string?' \
|
|
156
|
+
--dest=main_app
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
Or add to the migration manually before running.
|
|
160
|
+
|
|
161
|
+
### Customizing the Definition
|
|
162
|
+
|
|
163
|
+
Edit the generated definition:
|
|
164
|
+
|
|
165
|
+
```ruby
|
|
166
|
+
# app/definitions/profile_definition.rb
|
|
167
|
+
class ProfileDefinition < Plutonium::Resource::Definition
|
|
168
|
+
# Form configuration
|
|
169
|
+
form do |f|
|
|
170
|
+
f.field :bio
|
|
171
|
+
f.field :avatar
|
|
172
|
+
f.field :website
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
# Display configuration
|
|
176
|
+
display do |d|
|
|
177
|
+
d.field :bio
|
|
178
|
+
d.field :avatar
|
|
179
|
+
d.field :website
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
class ShowPage < ShowPage
|
|
183
|
+
private
|
|
184
|
+
|
|
185
|
+
def render_after_content
|
|
186
|
+
render Plutonium::Profile::SecuritySection.new
|
|
187
|
+
end
|
|
188
|
+
end
|
|
189
|
+
end
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Custom Security Section
|
|
193
|
+
|
|
194
|
+
Override the SecuritySection or create your own:
|
|
195
|
+
|
|
196
|
+
```ruby
|
|
197
|
+
class ProfileDefinition < Plutonium::Resource::Definition
|
|
198
|
+
class ShowPage < ShowPage
|
|
199
|
+
private
|
|
200
|
+
|
|
201
|
+
def render_after_content
|
|
202
|
+
render CustomSecuritySection.new
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
### Adding Custom Actions
|
|
209
|
+
|
|
210
|
+
Add profile-specific actions:
|
|
211
|
+
|
|
212
|
+
```ruby
|
|
213
|
+
class ProfileDefinition < Plutonium::Resource::Definition
|
|
214
|
+
action :export_data,
|
|
215
|
+
interaction: Profile::ExportDataInteraction
|
|
216
|
+
|
|
217
|
+
action :verify_email,
|
|
218
|
+
interaction: Profile::VerifyEmailInteraction,
|
|
219
|
+
category: :secondary
|
|
220
|
+
end
|
|
221
|
+
```
|
|
222
|
+
|
|
223
|
+
## Profile Link in Header
|
|
224
|
+
|
|
225
|
+
To add a profile link to the resource header, the `profile_url` helper is available via `Plutonium::Auth::Rodauth`:
|
|
226
|
+
|
|
227
|
+
```ruby
|
|
228
|
+
# In your controller or view
|
|
229
|
+
if respond_to?(:profile_url)
|
|
230
|
+
link_to "Profile", profile_url
|
|
231
|
+
end
|
|
232
|
+
```
|
|
233
|
+
|
|
234
|
+
This helper is automatically available when Profile is connected to a portal.
|
|
235
|
+
|
|
236
|
+
## Troubleshooting
|
|
237
|
+
|
|
238
|
+
### "User model not found"
|
|
239
|
+
|
|
240
|
+
Ensure the User model exists at `app/models/user.rb` with the marker comment:
|
|
241
|
+
|
|
242
|
+
```ruby
|
|
243
|
+
class User < ApplicationRecord
|
|
244
|
+
# add has_one associations above.
|
|
245
|
+
end
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
### "Definition path not found"
|
|
249
|
+
|
|
250
|
+
If using a package destination, ensure the package exists:
|
|
251
|
+
|
|
252
|
+
```bash
|
|
253
|
+
# Check available packages
|
|
254
|
+
ls packages/
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
### Profile Not Loading
|
|
258
|
+
|
|
259
|
+
Ensure the Profile is connected to your portal:
|
|
260
|
+
|
|
261
|
+
```bash
|
|
262
|
+
rails g pu:res:conn Profile --dest=my_portal --singular
|
|
263
|
+
```
|
|
264
|
+
|
|
265
|
+
And the user has a profile:
|
|
266
|
+
|
|
267
|
+
```ruby
|
|
268
|
+
current_user.profile || current_user.create_profile
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
## Related Skills
|
|
272
|
+
|
|
273
|
+
- `plutonium-rodauth` - Authentication configuration
|
|
274
|
+
- `plutonium-definition` - Customizing the profile definition
|
|
275
|
+
- `plutonium-views` - Custom pages and components
|
|
276
|
+
- `plutonium-connect-resource` - Connecting resources to portals
|
|
@@ -346,12 +346,34 @@ Available kit methods:
|
|
|
346
346
|
- `TabList(items:)`
|
|
347
347
|
- `EmptyCard(message)`
|
|
348
348
|
- `ActionButton(action, url:)`
|
|
349
|
-
- `DynaFrameHost()`
|
|
349
|
+
- `DynaFrameHost(src:, loading:)` - Lazy-loading turbo frame
|
|
350
|
+
- `DynaFrameContent(content) { |frame| ... }` - Frame-aware content wrapper
|
|
350
351
|
- `TableSearchBar()`
|
|
351
352
|
- `TableScopesBar()`
|
|
352
353
|
- `TableInfo(pagy)`
|
|
353
354
|
- `TablePagination(pagy)`
|
|
354
355
|
|
|
356
|
+
## DynaFrameContent Pattern
|
|
357
|
+
|
|
358
|
+
`DynaFrameContent` enables frame-aware rendering. For turbo-frame requests, only the content is rendered inside the frame. For regular requests, the full page renders with header/footer.
|
|
359
|
+
|
|
360
|
+
```ruby
|
|
361
|
+
# How Page::Base uses DynaFrameContent
|
|
362
|
+
def view_template(&block)
|
|
363
|
+
DynaFrameContent(page_content(block)) do |frame|
|
|
364
|
+
render_header # Skipped for frame requests
|
|
365
|
+
frame.render_content # Always rendered (in turbo-frame for frame requests)
|
|
366
|
+
render_footer # Skipped for frame requests
|
|
367
|
+
end
|
|
368
|
+
end
|
|
369
|
+
```
|
|
370
|
+
|
|
371
|
+
This pattern means:
|
|
372
|
+
- **Regular page load**: Full page with header, content, footer
|
|
373
|
+
- **Turbo-frame request**: Only `<turbo-frame id="...">` with content inside
|
|
374
|
+
|
|
375
|
+
All pages automatically inherit this behavior. No special handling needed for modals or frame navigation.
|
|
376
|
+
|
|
355
377
|
## Custom Components
|
|
356
378
|
|
|
357
379
|
### Creating a Phlex Component
|
data/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,39 @@
|
|
|
1
|
+
## [0.43.0] - 2026-03-05
|
|
2
|
+
|
|
3
|
+
### ๐ Features
|
|
4
|
+
|
|
5
|
+
- *(generators)* Add TypeSpec API specification generator
|
|
6
|
+
- *(forms)* Make submit_and_continue button configurable
|
|
7
|
+
- *(generators)* Add package destination and namespace handling to invites
|
|
8
|
+
- *(controller)* Auto-detect entity association by class
|
|
9
|
+
- *(generators)* Add profile generators for user settings pages
|
|
10
|
+
- *(auth)* Add profile_url helper method to rodauth module
|
|
11
|
+
|
|
12
|
+
### ๐ Bug Fixes
|
|
13
|
+
|
|
14
|
+
- *(ui)* Support custom primary keys and optional timestamps
|
|
15
|
+
- *(routing)* Handle singular resources and entity scoping correctly
|
|
16
|
+
- *(generators)* Improve robustness and package support
|
|
17
|
+
- *(resource)* Handle class reloading in associated_with scope
|
|
18
|
+
- *(ui)* Show profile link in user menu only when profile_url defined
|
|
19
|
+
- *(generators)* Fix invites templates and null attribute handling
|
|
20
|
+
|
|
21
|
+
### ๐ Refactor
|
|
22
|
+
|
|
23
|
+
- *(ui)* Extract breadcrumb rendering methods and add tests
|
|
24
|
+
|
|
25
|
+
### ๐ Documentation
|
|
26
|
+
|
|
27
|
+
- Add profile guide and update skill documentation
|
|
28
|
+
|
|
29
|
+
### ๐งช Testing
|
|
30
|
+
|
|
31
|
+
- Add OrgPortal fixture for entity scoping tests
|
|
32
|
+
- Add tests for routing, authorization, and display helpers
|
|
33
|
+
|
|
34
|
+
### โ๏ธ Miscellaneous Tasks
|
|
35
|
+
|
|
36
|
+
- Add profile_url stub to controller template and test fixtures
|
|
1
37
|
## [0.42.0] - 2026-02-14
|
|
2
38
|
|
|
3
39
|
### ๐ Features
|