plutonium 0.60.5 → 0.61.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/SKILL.md +19 -1
- data/.claude/skills/plutonium-app/SKILL.md +41 -0
- data/.claude/skills/plutonium-auth/SKILL.md +40 -0
- data/.claude/skills/plutonium-behavior/SKILL.md +47 -1
- data/.claude/skills/plutonium-kanban/SKILL.md +313 -0
- data/.claude/skills/plutonium-resource/SKILL.md +40 -0
- data/.claude/skills/plutonium-tenancy/SKILL.md +43 -0
- data/.claude/skills/plutonium-testing/SKILL.md +38 -0
- data/.claude/skills/plutonium-ui/SKILL.md +51 -0
- data/.claude/skills/plutonium-wizard/SKILL.md +469 -0
- data/.cliff.toml +6 -0
- data/Appraisals +3 -0
- data/CHANGELOG.md +549 -439
- data/CLAUDE.md +15 -7
- data/app/assets/plutonium.css +1 -1
- data/app/assets/plutonium.js +895 -193
- data/app/assets/plutonium.js.map +4 -4
- data/app/assets/plutonium.min.js +53 -53
- data/app/assets/plutonium.min.js.map +4 -4
- data/app/views/layouts/basic.html.erb +7 -0
- data/app/views/plutonium/_flash_toasts.html.erb +2 -46
- data/app/views/plutonium/_toast.html.erb +52 -0
- data/app/views/resource/_resource_kanban.html.erb +1 -0
- data/db/migrate/wizard/20260615000001_create_plutonium_wizard_sessions.rb +57 -0
- data/docs/.vitepress/config.ts +24 -0
- data/docs/guides/index.md +2 -0
- data/docs/guides/kanban.md +447 -0
- data/docs/guides/wizards.md +447 -0
- data/docs/public/images/guides/kanban-after-move.png +0 -0
- data/docs/public/images/guides/kanban-board-light.png +0 -0
- data/docs/public/images/guides/kanban-board.png +0 -0
- data/docs/public/images/guides/kanban-show-centered-modal.png +0 -0
- data/docs/public/images/guides/kanban-wip-toast.png +0 -0
- data/docs/public/images/guides/wizards-chooser.png +0 -0
- data/docs/public/images/guides/wizards-completed.png +0 -0
- data/docs/public/images/guides/wizards-index-action.png +0 -0
- data/docs/public/images/guides/wizards-repeater.png +0 -0
- data/docs/public/images/guides/wizards-review.png +0 -0
- data/docs/public/images/guides/wizards-step.png +0 -0
- data/docs/reference/behavior/policies.md +1 -1
- data/docs/reference/index.md +14 -0
- data/docs/reference/kanban/authorization.md +62 -0
- data/docs/reference/kanban/dsl.md +293 -0
- data/docs/reference/kanban/index.md +40 -0
- data/docs/reference/kanban/positioning.md +162 -0
- data/docs/reference/resource/definition.md +16 -0
- data/docs/reference/ui/forms.md +36 -0
- data/docs/reference/ui/pages.md +2 -0
- data/docs/reference/wizard/anchoring-resume.md +194 -0
- data/docs/reference/wizard/dsl.md +332 -0
- data/docs/reference/wizard/index.md +33 -0
- data/docs/reference/wizard/one-time.md +129 -0
- data/docs/reference/wizard/registration-launch.md +177 -0
- data/docs/reference/wizard/storage-config.md +151 -0
- data/docs/superpowers/plans/2026-06-14-form-sectioning.md +2 -2
- data/docs/superpowers/plans/2026-06-15-wizard-dsl.md +1619 -0
- data/docs/superpowers/plans/2026-06-15-wizard-dsl.md.tasks.json +68 -0
- data/docs/superpowers/plans/2026-06-26-kanban-dsl.md +1128 -0
- data/docs/superpowers/plans/2026-06-26-kanban-dsl.md.tasks.json +24 -0
- data/docs/superpowers/specs/2026-06-15-wizard-dsl-design.md +836 -0
- data/docs/superpowers/specs/2026-06-15-wizard-dsl-examples.rb +245 -0
- data/docs/superpowers/specs/2026-06-17-wizard-relaunch-prompt-design.md +86 -0
- data/docs/superpowers/specs/2026-06-18-wizard-attachments-design.md +101 -0
- data/docs/superpowers/specs/2026-06-18-wizard-hosting-design.md +220 -0
- data/docs/superpowers/specs/2026-06-26-kanban-dsl-design.md +388 -0
- data/gemfiles/postgres.gemfile +8 -0
- data/gemfiles/postgres.gemfile.lock +321 -0
- data/gemfiles/rails_7.gemfile +1 -0
- data/gemfiles/rails_7.gemfile.lock +1 -1
- data/gemfiles/rails_8.0.gemfile +1 -0
- data/gemfiles/rails_8.0.gemfile.lock +1 -1
- data/gemfiles/rails_8.1.gemfile +1 -0
- data/gemfiles/rails_8.1.gemfile.lock +14 -1
- data/lib/generators/pu/invites/templates/packages/invites/app/controllers/invites/user_invitations_controller.rb.tt +6 -1
- data/lib/plutonium/action/base.rb +9 -0
- data/lib/plutonium/auth/rodauth.rb +1 -2
- data/lib/plutonium/configuration.rb +4 -0
- data/lib/plutonium/core/controller.rb +20 -1
- data/lib/plutonium/definition/base.rb +25 -0
- data/lib/plutonium/definition/form_layout.rb +54 -35
- data/lib/plutonium/definition/index_views.rb +54 -1
- data/lib/plutonium/definition/wizards.rb +209 -0
- data/lib/plutonium/invites/concerns/invite_token.rb +9 -0
- data/lib/plutonium/invites/concerns/invite_user.rb +9 -0
- data/lib/plutonium/invites/controller.rb +4 -1
- data/lib/plutonium/kanban/action.rb +7 -0
- data/lib/plutonium/kanban/board.rb +40 -0
- data/lib/plutonium/kanban/broadcaster.rb +54 -0
- data/lib/plutonium/kanban/column.rb +69 -0
- data/lib/plutonium/kanban/context.rb +15 -0
- data/lib/plutonium/kanban/dsl.rb +71 -0
- data/lib/plutonium/kanban/grouping.rb +51 -0
- data/lib/plutonium/kanban/positioning.rb +75 -0
- data/lib/plutonium/kanban.rb +11 -0
- data/lib/plutonium/migrations.rb +40 -0
- data/lib/plutonium/positioning.rb +146 -0
- data/lib/plutonium/railtie.rb +33 -0
- data/lib/plutonium/resource/controller.rb +2 -0
- data/lib/plutonium/resource/controllers/crud_actions.rb +1 -1
- data/lib/plutonium/resource/controllers/kanban_actions.rb +455 -0
- data/lib/plutonium/resource/controllers/wizard_actions.rb +165 -0
- data/lib/plutonium/resource/policy.rb +8 -0
- data/lib/plutonium/routing/mapper_extensions.rb +44 -0
- data/lib/plutonium/routing/wizard_registration.rb +289 -0
- data/lib/plutonium/ui/display/resource.rb +17 -12
- data/lib/plutonium/ui/form/base.rb +19 -5
- data/lib/plutonium/ui/form/components/password.rb +126 -0
- data/lib/plutonium/ui/form/components/uppy.rb +6 -3
- data/lib/plutonium/ui/form/options/inferred_types.rb +20 -0
- data/lib/plutonium/ui/form/resource.rb +1 -1
- data/lib/plutonium/ui/form/wizard.rb +63 -0
- data/lib/plutonium/ui/grid/card.rb +16 -5
- data/lib/plutonium/ui/kanban/card.rb +67 -0
- data/lib/plutonium/ui/kanban/color_dot.rb +36 -0
- data/lib/plutonium/ui/kanban/column.rb +324 -0
- data/lib/plutonium/ui/kanban/resource.rb +212 -0
- data/lib/plutonium/ui/layout/resource_layout.rb +7 -1
- data/lib/plutonium/ui/modal/base.rb +30 -3
- data/lib/plutonium/ui/modal/centered.rb +5 -2
- data/lib/plutonium/ui/page/index.rb +1 -0
- data/lib/plutonium/ui/page/show.rb +23 -0
- data/lib/plutonium/ui/page/wizard.rb +371 -0
- data/lib/plutonium/ui/page/wizard_chooser.rb +97 -0
- data/lib/plutonium/ui/page/wizard_completed.rb +86 -0
- data/lib/plutonium/ui/table/base.rb +1 -1
- data/lib/plutonium/ui/table/components/view_switcher.rb +2 -1
- data/lib/plutonium/ui/wizard/review.rb +196 -0
- data/lib/plutonium/ui/wizard/stepper.rb +122 -0
- data/lib/plutonium/ui/wizard/summary_display.rb +59 -0
- data/lib/plutonium/version.rb +1 -1
- data/lib/plutonium/wizard/attachment_data.rb +42 -0
- data/lib/plutonium/wizard/attachments.rb +226 -0
- data/lib/plutonium/wizard/base.rb +216 -0
- data/lib/plutonium/wizard/base_controller.rb +31 -0
- data/lib/plutonium/wizard/configuration.rb +42 -0
- data/lib/plutonium/wizard/controller.rb +162 -0
- data/lib/plutonium/wizard/data.rb +134 -0
- data/lib/plutonium/wizard/driving.rb +639 -0
- data/lib/plutonium/wizard/dsl.rb +336 -0
- data/lib/plutonium/wizard/errors.rb +27 -0
- data/lib/plutonium/wizard/field_capture.rb +157 -0
- data/lib/plutonium/wizard/field_importer.rb +208 -0
- data/lib/plutonium/wizard/gate.rb +171 -0
- data/lib/plutonium/wizard/instance_key.rb +97 -0
- data/lib/plutonium/wizard/lazy_persisted.rb +77 -0
- data/lib/plutonium/wizard/resume.rb +250 -0
- data/lib/plutonium/wizard/review_step.rb +48 -0
- data/lib/plutonium/wizard/route_resolution.rb +40 -0
- data/lib/plutonium/wizard/runner.rb +684 -0
- data/lib/plutonium/wizard/session.rb +53 -0
- data/lib/plutonium/wizard/state.rb +35 -0
- data/lib/plutonium/wizard/step.rb +61 -0
- data/lib/plutonium/wizard/step_adapter.rb +103 -0
- data/lib/plutonium/wizard/store/active_record.rb +174 -0
- data/lib/plutonium/wizard/store/base.rb +42 -0
- data/lib/plutonium/wizard/store/memory.rb +44 -0
- data/lib/plutonium/wizard/sweep_job.rb +76 -0
- data/lib/plutonium/wizard.rb +86 -0
- data/lib/plutonium.rb +5 -0
- data/lib/rodauth/features/case_insensitive_login.rb +1 -1
- data/lib/tasks/release.rake +144 -191
- data/package.json +3 -3
- data/src/css/components.css +132 -0
- data/src/js/controllers/attachment_input_controller.js +15 -1
- data/src/js/controllers/dirty_form_guard_controller.js +155 -27
- data/src/js/controllers/kanban_controller.js +330 -0
- data/src/js/controllers/password_sentinel_controller.js +39 -0
- data/src/js/controllers/register_controllers.js +6 -0
- data/src/js/controllers/remote_modal_controller.js +10 -0
- data/src/js/controllers/row_click_controller.js +14 -1
- data/src/js/controllers/wizard_controller.js +54 -0
- data/src/js/turbo/turbo_confirm.js +1 -1
- data/yarn.lock +271 -282
- metadata +100 -1
|
@@ -0,0 +1,321 @@
|
|
|
1
|
+
GEM
|
|
2
|
+
remote: https://rubygems.org/
|
|
3
|
+
specs:
|
|
4
|
+
action_text-trix (2.1.19)
|
|
5
|
+
railties
|
|
6
|
+
actioncable (8.1.3)
|
|
7
|
+
actionpack (= 8.1.3)
|
|
8
|
+
activesupport (= 8.1.3)
|
|
9
|
+
nio4r (~> 2.0)
|
|
10
|
+
websocket-driver (>= 0.6.1)
|
|
11
|
+
zeitwerk (~> 2.6)
|
|
12
|
+
actionmailbox (8.1.3)
|
|
13
|
+
actionpack (= 8.1.3)
|
|
14
|
+
activejob (= 8.1.3)
|
|
15
|
+
activerecord (= 8.1.3)
|
|
16
|
+
activestorage (= 8.1.3)
|
|
17
|
+
activesupport (= 8.1.3)
|
|
18
|
+
mail (>= 2.8.0)
|
|
19
|
+
actionmailer (8.1.3)
|
|
20
|
+
actionpack (= 8.1.3)
|
|
21
|
+
actionview (= 8.1.3)
|
|
22
|
+
activejob (= 8.1.3)
|
|
23
|
+
activesupport (= 8.1.3)
|
|
24
|
+
mail (>= 2.8.0)
|
|
25
|
+
rails-dom-testing (~> 2.2)
|
|
26
|
+
actionpack (8.1.3)
|
|
27
|
+
actionview (= 8.1.3)
|
|
28
|
+
activesupport (= 8.1.3)
|
|
29
|
+
nokogiri (>= 1.8.5)
|
|
30
|
+
rack (>= 2.2.4)
|
|
31
|
+
rack-session (>= 1.0.1)
|
|
32
|
+
rack-test (>= 0.6.3)
|
|
33
|
+
rails-dom-testing (~> 2.2)
|
|
34
|
+
rails-html-sanitizer (~> 1.6)
|
|
35
|
+
useragent (~> 0.16)
|
|
36
|
+
actiontext (8.1.3)
|
|
37
|
+
action_text-trix (~> 2.1.15)
|
|
38
|
+
actionpack (= 8.1.3)
|
|
39
|
+
activerecord (= 8.1.3)
|
|
40
|
+
activestorage (= 8.1.3)
|
|
41
|
+
activesupport (= 8.1.3)
|
|
42
|
+
globalid (>= 0.6.0)
|
|
43
|
+
nokogiri (>= 1.8.5)
|
|
44
|
+
actionview (8.1.3)
|
|
45
|
+
activesupport (= 8.1.3)
|
|
46
|
+
builder (~> 3.1)
|
|
47
|
+
erubi (~> 1.11)
|
|
48
|
+
rails-dom-testing (~> 2.2)
|
|
49
|
+
rails-html-sanitizer (~> 1.6)
|
|
50
|
+
activejob (8.1.3)
|
|
51
|
+
activesupport (= 8.1.3)
|
|
52
|
+
globalid (>= 0.3.6)
|
|
53
|
+
activemodel (8.1.3)
|
|
54
|
+
activesupport (= 8.1.3)
|
|
55
|
+
activerecord (8.1.3)
|
|
56
|
+
activemodel (= 8.1.3)
|
|
57
|
+
activesupport (= 8.1.3)
|
|
58
|
+
timeout (>= 0.4.0)
|
|
59
|
+
activestorage (8.1.3)
|
|
60
|
+
actionpack (= 8.1.3)
|
|
61
|
+
activejob (= 8.1.3)
|
|
62
|
+
activerecord (= 8.1.3)
|
|
63
|
+
activesupport (= 8.1.3)
|
|
64
|
+
marcel (~> 1.0)
|
|
65
|
+
activesupport (8.1.3)
|
|
66
|
+
base64
|
|
67
|
+
bigdecimal
|
|
68
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
|
69
|
+
connection_pool (>= 2.2.5)
|
|
70
|
+
drb
|
|
71
|
+
i18n (>= 1.6, < 2)
|
|
72
|
+
json
|
|
73
|
+
logger (>= 1.4.2)
|
|
74
|
+
minitest (>= 5.1)
|
|
75
|
+
securerandom (>= 0.3)
|
|
76
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
|
77
|
+
uri (>= 0.13.1)
|
|
78
|
+
base64 (0.3.0)
|
|
79
|
+
bigdecimal (4.1.2)
|
|
80
|
+
builder (3.3.0)
|
|
81
|
+
concurrent-ruby (1.3.7)
|
|
82
|
+
connection_pool (3.0.2)
|
|
83
|
+
crass (1.0.7)
|
|
84
|
+
date (3.5.1)
|
|
85
|
+
drb (2.2.3)
|
|
86
|
+
erb (6.0.4)
|
|
87
|
+
erubi (1.13.1)
|
|
88
|
+
globalid (1.4.0)
|
|
89
|
+
activesupport (>= 6.1)
|
|
90
|
+
i18n (1.15.2)
|
|
91
|
+
concurrent-ruby (~> 1.0)
|
|
92
|
+
io-console (0.8.2)
|
|
93
|
+
irb (1.18.0)
|
|
94
|
+
pp (>= 0.6.0)
|
|
95
|
+
prism (>= 1.3.0)
|
|
96
|
+
rdoc (>= 4.0.0)
|
|
97
|
+
reline (>= 0.4.2)
|
|
98
|
+
json (2.20.0)
|
|
99
|
+
logger (1.7.0)
|
|
100
|
+
loofah (2.25.1)
|
|
101
|
+
crass (~> 1.0.2)
|
|
102
|
+
nokogiri (>= 1.12.0)
|
|
103
|
+
mail (2.9.0)
|
|
104
|
+
logger
|
|
105
|
+
mini_mime (>= 0.1.1)
|
|
106
|
+
net-imap
|
|
107
|
+
net-pop
|
|
108
|
+
net-smtp
|
|
109
|
+
marcel (1.2.1)
|
|
110
|
+
mini_mime (1.1.5)
|
|
111
|
+
mini_portile2 (2.8.9)
|
|
112
|
+
minitest (6.0.6)
|
|
113
|
+
drb (~> 2.0)
|
|
114
|
+
prism (~> 1.5)
|
|
115
|
+
net-imap (0.6.4.1)
|
|
116
|
+
date
|
|
117
|
+
net-protocol
|
|
118
|
+
net-pop (0.1.2)
|
|
119
|
+
net-protocol
|
|
120
|
+
net-protocol (0.2.2)
|
|
121
|
+
timeout
|
|
122
|
+
net-smtp (0.5.1)
|
|
123
|
+
net-protocol
|
|
124
|
+
nio4r (2.7.5)
|
|
125
|
+
nokogiri (1.19.4)
|
|
126
|
+
mini_portile2 (~> 2.8.2)
|
|
127
|
+
racc (~> 1.4)
|
|
128
|
+
nokogiri (1.19.4-aarch64-linux-gnu)
|
|
129
|
+
racc (~> 1.4)
|
|
130
|
+
nokogiri (1.19.4-aarch64-linux-musl)
|
|
131
|
+
racc (~> 1.4)
|
|
132
|
+
nokogiri (1.19.4-arm-linux-gnu)
|
|
133
|
+
racc (~> 1.4)
|
|
134
|
+
nokogiri (1.19.4-arm-linux-musl)
|
|
135
|
+
racc (~> 1.4)
|
|
136
|
+
nokogiri (1.19.4-arm64-darwin)
|
|
137
|
+
racc (~> 1.4)
|
|
138
|
+
nokogiri (1.19.4-x86_64-darwin)
|
|
139
|
+
racc (~> 1.4)
|
|
140
|
+
nokogiri (1.19.4-x86_64-linux-gnu)
|
|
141
|
+
racc (~> 1.4)
|
|
142
|
+
nokogiri (1.19.4-x86_64-linux-musl)
|
|
143
|
+
racc (~> 1.4)
|
|
144
|
+
pg (1.6.3)
|
|
145
|
+
pg (1.6.3-aarch64-linux)
|
|
146
|
+
pg (1.6.3-aarch64-linux-musl)
|
|
147
|
+
pg (1.6.3-arm64-darwin)
|
|
148
|
+
pg (1.6.3-x86_64-darwin)
|
|
149
|
+
pg (1.6.3-x86_64-linux)
|
|
150
|
+
pg (1.6.3-x86_64-linux-musl)
|
|
151
|
+
pp (0.6.4)
|
|
152
|
+
prettyprint
|
|
153
|
+
prettyprint (0.2.0)
|
|
154
|
+
prism (1.9.0)
|
|
155
|
+
racc (1.8.1)
|
|
156
|
+
rack (3.2.6)
|
|
157
|
+
rack-session (2.1.2)
|
|
158
|
+
base64 (>= 0.1.0)
|
|
159
|
+
rack (>= 3.0.0)
|
|
160
|
+
rack-test (2.2.0)
|
|
161
|
+
rack (>= 1.3)
|
|
162
|
+
rackup (2.3.1)
|
|
163
|
+
rack (>= 3)
|
|
164
|
+
rails (8.1.3)
|
|
165
|
+
actioncable (= 8.1.3)
|
|
166
|
+
actionmailbox (= 8.1.3)
|
|
167
|
+
actionmailer (= 8.1.3)
|
|
168
|
+
actionpack (= 8.1.3)
|
|
169
|
+
actiontext (= 8.1.3)
|
|
170
|
+
actionview (= 8.1.3)
|
|
171
|
+
activejob (= 8.1.3)
|
|
172
|
+
activemodel (= 8.1.3)
|
|
173
|
+
activerecord (= 8.1.3)
|
|
174
|
+
activestorage (= 8.1.3)
|
|
175
|
+
activesupport (= 8.1.3)
|
|
176
|
+
bundler (>= 1.15.0)
|
|
177
|
+
railties (= 8.1.3)
|
|
178
|
+
rails-dom-testing (2.3.0)
|
|
179
|
+
activesupport (>= 5.0.0)
|
|
180
|
+
minitest
|
|
181
|
+
nokogiri (>= 1.6)
|
|
182
|
+
rails-html-sanitizer (1.7.0)
|
|
183
|
+
loofah (~> 2.25)
|
|
184
|
+
nokogiri (>= 1.15.7, != 1.16.7, != 1.16.6, != 1.16.5, != 1.16.4, != 1.16.3, != 1.16.2, != 1.16.1, != 1.16.0.rc1, != 1.16.0)
|
|
185
|
+
railties (8.1.3)
|
|
186
|
+
actionpack (= 8.1.3)
|
|
187
|
+
activesupport (= 8.1.3)
|
|
188
|
+
irb (~> 1.13)
|
|
189
|
+
rackup (>= 1.0.0)
|
|
190
|
+
rake (>= 12.2)
|
|
191
|
+
thor (~> 1.0, >= 1.2.2)
|
|
192
|
+
tsort (>= 0.2)
|
|
193
|
+
zeitwerk (~> 2.6)
|
|
194
|
+
rake (13.4.2)
|
|
195
|
+
rbs (4.0.3)
|
|
196
|
+
logger
|
|
197
|
+
prism (>= 1.6.0)
|
|
198
|
+
tsort
|
|
199
|
+
rdoc (8.0.0)
|
|
200
|
+
erb
|
|
201
|
+
prism (>= 1.6.0)
|
|
202
|
+
rbs (>= 4.0.0)
|
|
203
|
+
tsort
|
|
204
|
+
reline (0.6.3)
|
|
205
|
+
io-console (~> 0.5)
|
|
206
|
+
securerandom (0.4.1)
|
|
207
|
+
thor (1.5.0)
|
|
208
|
+
timeout (0.6.1)
|
|
209
|
+
tsort (0.2.0)
|
|
210
|
+
tzinfo (2.0.6)
|
|
211
|
+
concurrent-ruby (~> 1.0)
|
|
212
|
+
uri (1.1.1)
|
|
213
|
+
useragent (0.16.11)
|
|
214
|
+
websocket-driver (0.8.2)
|
|
215
|
+
base64
|
|
216
|
+
websocket-extensions (>= 0.1.0)
|
|
217
|
+
websocket-extensions (0.1.5)
|
|
218
|
+
zeitwerk (2.8.2)
|
|
219
|
+
|
|
220
|
+
PLATFORMS
|
|
221
|
+
aarch64-linux
|
|
222
|
+
aarch64-linux-gnu
|
|
223
|
+
aarch64-linux-musl
|
|
224
|
+
arm-linux-gnu
|
|
225
|
+
arm-linux-musl
|
|
226
|
+
arm64-darwin
|
|
227
|
+
ruby
|
|
228
|
+
x86_64-darwin
|
|
229
|
+
x86_64-linux
|
|
230
|
+
x86_64-linux-gnu
|
|
231
|
+
x86_64-linux-musl
|
|
232
|
+
|
|
233
|
+
DEPENDENCIES
|
|
234
|
+
pg (~> 1.5)
|
|
235
|
+
rails (~> 8.1.0)
|
|
236
|
+
|
|
237
|
+
CHECKSUMS
|
|
238
|
+
action_text-trix (2.1.19) sha256=7012f59421009cf284aa651294896414d653a61a2417c9b8714c8476d2f74009
|
|
239
|
+
actioncable (8.1.3) sha256=e5bc7f75e44e6a22de29c4f43176927c3a9ce4824464b74ed18d8226e75a80f0
|
|
240
|
+
actionmailbox (8.1.3) sha256=df7da474eaa0e70df4ed5a6fef66eb3b3b0f2dbf7f14518deee8d77f1b4aae59
|
|
241
|
+
actionmailer (8.1.3) sha256=831f724891bb70d0aaa4d76581a6321124b6a752cb655c9346aae5479318448d
|
|
242
|
+
actionpack (8.1.3) sha256=af998cae4d47c5d581a2cc363b5c77eb718b7c4b45748d81b1887b25621c29a3
|
|
243
|
+
actiontext (8.1.3) sha256=d291019c00e1ea9e6463011fa214f6081a56d7b9a1d224e7d3f6384c1dafc7d2
|
|
244
|
+
actionview (8.1.3) sha256=1347c88c7f3edb38100c5ce0e9fb5e62d7755f3edc1b61cce2eb0b2c6ea2fd5d
|
|
245
|
+
activejob (8.1.3) sha256=a149b1766aa8204c3c3da7309e4becd40fcd5529c348cffbf6c9b16b565fe8d3
|
|
246
|
+
activemodel (8.1.3) sha256=90c05cbe4cef3649b8f79f13016191ea94c4525ce4a5c0fb7ef909c4b91c8219
|
|
247
|
+
activerecord (8.1.3) sha256=8003be7b2466ba0a2a670e603eeb0a61dd66058fccecfc49901e775260ac70ab
|
|
248
|
+
activestorage (8.1.3) sha256=0564ce9309143951a67615e1bb4e090ee54b8befed417133cae614479b46384d
|
|
249
|
+
activesupport (8.1.3) sha256=21a5e0dfbd4c3ddd9e1317ec6a4d782fa226e7867dc70b0743acda81a1dca20e
|
|
250
|
+
base64 (0.3.0) sha256=27337aeabad6ffae05c265c450490628ef3ebd4b67be58257393227588f5a97b
|
|
251
|
+
bigdecimal (4.1.2) sha256=53d217666027eab4280346fba98e7d5b66baaae1b9c3c1c0ffe89d48188a3fbd
|
|
252
|
+
builder (3.3.0) sha256=497918d2f9dca528fdca4b88d84e4ef4387256d984b8154e9d5d3fe5a9c8835f
|
|
253
|
+
concurrent-ruby (1.3.7) sha256=4412caec3a5ea2e5fdc52076724c071a81f2c0593d83b2ac8cbb8ca63b3151b0
|
|
254
|
+
connection_pool (3.0.2) sha256=33fff5ba71a12d2aa26cb72b1db8bba2a1a01823559fb01d29eb74c286e62e0a
|
|
255
|
+
crass (1.0.7) sha256=94868719948664c89ddcaf0a37c65048413dfcb1c869470a5f7a7ceb5390b295
|
|
256
|
+
date (3.5.1) sha256=750d06384d7b9c15d562c76291407d89e368dda4d4fff957eb94962d325a0dc0
|
|
257
|
+
drb (2.2.3) sha256=0b00d6fdb50995fe4a45dea13663493c841112e4068656854646f418fda13373
|
|
258
|
+
erb (6.0.4) sha256=38e3803694be357fe2bfe312487c74beaf9fb4e5beb3e22498952fe1645b95d9
|
|
259
|
+
erubi (1.13.1) sha256=a082103b0885dbc5ecf1172fede897f9ebdb745a4b97a5e8dc63953db1ee4ad9
|
|
260
|
+
globalid (1.4.0) sha256=037f12fbf1d9d7a014d501c2d5c77356fd4ddd96d7a7991d6700bba96706f427
|
|
261
|
+
i18n (1.15.2) sha256=00f9eb62412fe593b2a65a97daa75300d37abb8f7202ec748e94b6d46a9dd1b5
|
|
262
|
+
io-console (0.8.2) sha256=d6e3ae7a7cc7574f4b8893b4fca2162e57a825b223a177b7afa236c5ef9814cc
|
|
263
|
+
irb (1.18.0) sha256=de9454a0703a54704b9811a5ef31a60c86949fbf4013fcf244fabc7c775248e3
|
|
264
|
+
json (2.20.0) sha256=9362bc6e55a952b056abf9167cf053358181c904cb70cd6eee0808ea830fc32b
|
|
265
|
+
logger (1.7.0) sha256=196edec7cc44b66cfb40f9755ce11b392f21f7967696af15d274dde7edff0203
|
|
266
|
+
loofah (2.25.1) sha256=d436c73dbd0c1147b16c4a41db097942d217303e1f7728704b37e4df9f6d2e04
|
|
267
|
+
mail (2.9.0) sha256=6fa6673ecd71c60c2d996260f9ee3dd387d4673b8169b502134659ece6d34941
|
|
268
|
+
marcel (1.2.1) sha256=1678e9360e32f9eafa917c80029e2f6d10b2715c66a4b87b6d0da9b9cd1f859f
|
|
269
|
+
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
|
|
270
|
+
mini_portile2 (2.8.9) sha256=0cd7c7f824e010c072e33f68bc02d85a00aeb6fce05bb4819c03dfd3c140c289
|
|
271
|
+
minitest (6.0.6) sha256=153ea36d1d987a62942382b61075745042a2b3123b1cd48f4c3675af9cc7d6f1
|
|
272
|
+
net-imap (0.6.4.1) sha256=29f0360d75a7efd3539f16ac1957dea5c0a51ddeceb348db4553c3120914ea0d
|
|
273
|
+
net-pop (0.1.2) sha256=848b4e982013c15b2f0382792268763b748cce91c9e91e36b0f27ed26420dff3
|
|
274
|
+
net-protocol (0.2.2) sha256=aa73e0cba6a125369de9837b8d8ef82a61849360eba0521900e2c3713aa162a8
|
|
275
|
+
net-smtp (0.5.1) sha256=ed96a0af63c524fceb4b29b0d352195c30d82dd916a42f03c62a3a70e5b70736
|
|
276
|
+
nio4r (2.7.5) sha256=6c90168e48fb5f8e768419c93abb94ba2b892a1d0602cb06eef16d8b7df1dca1
|
|
277
|
+
nokogiri (1.19.4) sha256=50c951611c92bca05c51411aef45f1cbc50f2821c4802758c5c6d34696533ab5
|
|
278
|
+
nokogiri (1.19.4-aarch64-linux-gnu) sha256=1269fb644a6de405057a53dd5c762b1209b43ca7424f839454d3dbc677c31a8f
|
|
279
|
+
nokogiri (1.19.4-aarch64-linux-musl) sha256=35c65b9ce72b3bb03207bdbe7067915019dc18c1b9b59139684bd6690fdd01af
|
|
280
|
+
nokogiri (1.19.4-arm-linux-gnu) sha256=a301313e38bb065d68239e79734bcd6f56fb6efaacebde29e9abf2a4735340ca
|
|
281
|
+
nokogiri (1.19.4-arm-linux-musl) sha256=588923c101bcfa78869734d247d25b598674323e7f22474fc468f6e5647311eb
|
|
282
|
+
nokogiri (1.19.4-arm64-darwin) sha256=a46db9853286e6597b36ebc6953817d15acf3a299583eb3f89fdc6f91dd63527
|
|
283
|
+
nokogiri (1.19.4-x86_64-darwin) sha256=7fd17057d3e1f00e9954a74b3cd76595d3d4a5ef233b7ed9599047c204f70551
|
|
284
|
+
nokogiri (1.19.4-x86_64-linux-gnu) sha256=379fae440b28915e3f19d752ce2dcf8465ed2b2fbefd2a7ca0dd497bc981a06a
|
|
285
|
+
nokogiri (1.19.4-x86_64-linux-musl) sha256=17dfb7c1fa194ae02fbf7c51a7afc8d278045ab3fdacfd86f91d02d7b274470b
|
|
286
|
+
pg (1.6.3) sha256=1388d0563e13d2758c1089e35e973a3249e955c659592d10e5b77c468f628a99
|
|
287
|
+
pg (1.6.3-aarch64-linux) sha256=0698ad563e02383c27510b76bf7d4cd2de19cd1d16a5013f375dd473e4be72ea
|
|
288
|
+
pg (1.6.3-aarch64-linux-musl) sha256=06a75f4ea04b05140146f2a10550b8e0d9f006a79cdaf8b5b130cde40e3ecc2c
|
|
289
|
+
pg (1.6.3-arm64-darwin) sha256=7240330b572e6355d7c75a7de535edb5dfcbd6295d9c7777df4d9dddfb8c0e5f
|
|
290
|
+
pg (1.6.3-x86_64-darwin) sha256=ee2e04a17c0627225054ffeb43e31a95be9d7e93abda2737ea3ce4a62f2729d6
|
|
291
|
+
pg (1.6.3-x86_64-linux) sha256=5d9e188c8f7a0295d162b7b88a768d8452a899977d44f3274d1946d67920ae8d
|
|
292
|
+
pg (1.6.3-x86_64-linux-musl) sha256=9c9c90d98c72f78eb04c0f55e9618fe55d1512128e411035fe229ff427864009
|
|
293
|
+
pp (0.6.4) sha256=dfcb0fce700c41456265922884f9fe195d7fbb0674a3578e6c0f69588e82b570
|
|
294
|
+
prettyprint (0.2.0) sha256=2bc9e15581a94742064a3cc8b0fb9d45aae3d03a1baa6ef80922627a0766f193
|
|
295
|
+
prism (1.9.0) sha256=7b530c6a9f92c24300014919c9dcbc055bf4cdf51ec30aed099b06cd6674ef85
|
|
296
|
+
racc (1.8.1) sha256=4a7f6929691dbec8b5209a0b373bc2614882b55fc5d2e447a21aaa691303d62f
|
|
297
|
+
rack (3.2.6) sha256=5ed78e1f73b2e25679bec7d45ee2d4483cc4146eb1be0264fc4d94cb5ef212c2
|
|
298
|
+
rack-session (2.1.2) sha256=595434f8c0c3473ae7d7ac56ecda6cc6dfd9d37c0b2b5255330aa1576967ffe8
|
|
299
|
+
rack-test (2.2.0) sha256=005a36692c306ac0b4a9350355ee080fd09ddef1148a5f8b2ac636c720f5c463
|
|
300
|
+
rackup (2.3.1) sha256=6c79c26753778e90983761d677a48937ee3192b3ffef6bc963c0950f94688868
|
|
301
|
+
rails (8.1.3) sha256=6d017ba5348c98fc909753a8169b21d44de14d2a0b92d140d1a966834c3c9cd3
|
|
302
|
+
rails-dom-testing (2.3.0) sha256=8acc7953a7b911ca44588bf08737bc16719f431a1cc3091a292bca7317925c1d
|
|
303
|
+
rails-html-sanitizer (1.7.0) sha256=28b145cceaf9cc214a9874feaa183c3acba036c9592b19886e0e45efc62b1e89
|
|
304
|
+
railties (8.1.3) sha256=913eb0e0cb520aac687ffd74916bd726d48fa21f47833c6292576ef6a286de22
|
|
305
|
+
rake (13.4.2) sha256=cb825b2bd5f1f8e91ca37bddb4b9aaf345551b4731da62949be002fa89283701
|
|
306
|
+
rbs (4.0.3) sha256=5a7bf70e2628549d9a1f44eae447b2cfe55968a9c60cfff52693a4bdcc020e14
|
|
307
|
+
rdoc (8.0.0) sha256=03bf8c08a9639658855a0cfd77c0abca8325c227693f7f33f82957811348c469
|
|
308
|
+
reline (0.6.3) sha256=1198b04973565b36ec0f11542ab3f5cfeeec34823f4e54cebde90968092b1835
|
|
309
|
+
securerandom (0.4.1) sha256=cc5193d414a4341b6e225f0cb4446aceca8e50d5e1888743fac16987638ea0b1
|
|
310
|
+
thor (1.5.0) sha256=e3a9e55fe857e44859ce104a84675ab6e8cd59c650a49106a05f55f136425e73
|
|
311
|
+
timeout (0.6.1) sha256=78f57368a7e7bbadec56971f78a3f5ecbcfb59b7fcbb0a3ed6ddc08a5094accb
|
|
312
|
+
tsort (0.2.0) sha256=9650a793f6859a43b6641671278f79cfead60ac714148aabe4e3f0060480089f
|
|
313
|
+
tzinfo (2.0.6) sha256=8daf828cc77bcf7d63b0e3bdb6caa47e2272dcfaf4fbfe46f8c3a9df087a829b
|
|
314
|
+
uri (1.1.1) sha256=379fa58d27ffb1387eaada68c749d1426738bd0f654d812fcc07e7568f5c57c6
|
|
315
|
+
useragent (0.16.11) sha256=700e6413ad4bb954bb63547fa098dddf7b0ebe75b40cc6f93b8d54255b173844
|
|
316
|
+
websocket-driver (0.8.2) sha256=97c556b019bf3410b4961002ac501621e9322d3f8a7bc02161a09301cc4c4146
|
|
317
|
+
websocket-extensions (0.1.5) sha256=1c6ba63092cda343eb53fc657110c71c754c56484aad42578495227d717a8241
|
|
318
|
+
zeitwerk (2.8.2) sha256=7212a61311083c604184b1ea2574b9aa05cd14f855a0841c06985cabe9181d12
|
|
319
|
+
|
|
320
|
+
BUNDLED WITH
|
|
321
|
+
4.0.6
|
data/gemfiles/rails_7.gemfile
CHANGED
data/gemfiles/rails_8.0.gemfile
CHANGED
data/gemfiles/rails_8.1.gemfile
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
PATH
|
|
2
2
|
remote: ..
|
|
3
3
|
specs:
|
|
4
|
-
plutonium (0.
|
|
4
|
+
plutonium (0.60.4)
|
|
5
5
|
action_policy (~> 0.7.0)
|
|
6
6
|
csv
|
|
7
7
|
listen (~> 3.8)
|
|
@@ -74,6 +74,11 @@ GEM
|
|
|
74
74
|
erubi (~> 1.11)
|
|
75
75
|
rails-dom-testing (~> 2.2)
|
|
76
76
|
rails-html-sanitizer (~> 1.6)
|
|
77
|
+
active_shrine (0.7.1)
|
|
78
|
+
activestorage
|
|
79
|
+
activesupport
|
|
80
|
+
railties
|
|
81
|
+
shrine
|
|
77
82
|
activejob (8.1.2)
|
|
78
83
|
activesupport (= 8.1.2)
|
|
79
84
|
globalid (>= 0.3.6)
|
|
@@ -137,9 +142,13 @@ GEM
|
|
|
137
142
|
thor (>= 0.14.6)
|
|
138
143
|
concurrent-ruby (1.3.6)
|
|
139
144
|
connection_pool (3.0.2)
|
|
145
|
+
content_disposition (1.0.0)
|
|
140
146
|
crass (1.0.6)
|
|
141
147
|
csv (3.3.5)
|
|
142
148
|
date (3.5.1)
|
|
149
|
+
down (5.6.0)
|
|
150
|
+
addressable (~> 2.8)
|
|
151
|
+
base64 (~> 0.3)
|
|
143
152
|
drb (2.2.3)
|
|
144
153
|
erb (6.0.2)
|
|
145
154
|
erubi (1.13.1)
|
|
@@ -369,6 +378,9 @@ GEM
|
|
|
369
378
|
sequel-activerecord_connection (2.0.1)
|
|
370
379
|
activerecord (>= 5.1)
|
|
371
380
|
sequel (~> 5.38)
|
|
381
|
+
shrine (3.7.1)
|
|
382
|
+
content_disposition (~> 1.0)
|
|
383
|
+
down (~> 5.1)
|
|
372
384
|
sin_lru_redux (2.5.2)
|
|
373
385
|
sqlite3 (2.9.1-arm64-darwin)
|
|
374
386
|
standard (1.54.0)
|
|
@@ -427,6 +439,7 @@ PLATFORMS
|
|
|
427
439
|
arm64-darwin
|
|
428
440
|
|
|
429
441
|
DEPENDENCIES
|
|
442
|
+
active_shrine
|
|
430
443
|
appraisal
|
|
431
444
|
bcrypt
|
|
432
445
|
brakeman
|
|
@@ -54,9 +54,14 @@ module Invites
|
|
|
54
54
|
|
|
55
55
|
<% if rodauth? -%>
|
|
56
56
|
def create_user_for_signup(email, password)
|
|
57
|
+
# Normalize the login up front. Lookups (account_from_login) downcase the
|
|
58
|
+
# login, so on a case-sensitive database a verbatim mixed-case email would
|
|
59
|
+
# be created but never found again. Downcasing here keeps create and
|
|
60
|
+
# lookup in agreement across both branches.
|
|
61
|
+
email = email.downcase
|
|
57
62
|
password_hash = rodauth.password_hash(password)
|
|
58
63
|
|
|
59
|
-
if email
|
|
64
|
+
if email == @invite.email.downcase
|
|
60
65
|
# Email matches invitation - create verified account directly
|
|
61
66
|
<%= user_model %>.create!(
|
|
62
67
|
email: email,
|
|
@@ -49,8 +49,17 @@ module Plutonium
|
|
|
49
49
|
# Downgrades the remote-modal frame to nil when the definition has
|
|
50
50
|
# `modal false`, so the link navigates as a full page instead of
|
|
51
51
|
# targeting a frame that won't exist. Other frames pass through.
|
|
52
|
+
#
|
|
53
|
+
# The canonical :show action carries no explicit frame; instead it reads
|
|
54
|
+
# the definition's `show_in` so a resource can open its show page in a
|
|
55
|
+
# modal (`show_in :modal`) or full-page (`:page`, default) without the
|
|
56
|
+
# caller threading a frame. This is deliberately independent of
|
|
57
|
+
# `modal_mode` (which styles :new/:edit) — show is always centered.
|
|
52
58
|
def turbo_frame(definition = nil)
|
|
53
59
|
return nil if definition && targets_remote_modal? && definition.modal_mode == false
|
|
60
|
+
if definition && name == :show && @turbo_frame.nil?
|
|
61
|
+
return (definition.show_in == :modal) ? Plutonium::REMOTE_MODAL_FRAME : nil
|
|
62
|
+
end
|
|
54
63
|
@turbo_frame
|
|
55
64
|
end
|
|
56
65
|
|
|
@@ -7,7 +7,7 @@ module Plutonium
|
|
|
7
7
|
extend ActiveSupport::Concern
|
|
8
8
|
|
|
9
9
|
included do
|
|
10
|
-
helper_method :current_user
|
|
10
|
+
helper_method :current_user
|
|
11
11
|
helper_method :logout_url
|
|
12
12
|
helper_method :profile_url
|
|
13
13
|
end
|
|
@@ -23,7 +23,6 @@ module Plutonium
|
|
|
23
23
|
def current_user
|
|
24
24
|
rodauth.rails_account
|
|
25
25
|
end
|
|
26
|
-
alias_method :current_#{name}, :current_user
|
|
27
26
|
|
|
28
27
|
def logout_url
|
|
29
28
|
rodauth.logout_path
|
|
@@ -24,6 +24,9 @@ module Plutonium
|
|
|
24
24
|
# @return [AssetConfiguration] asset configuration
|
|
25
25
|
attr_reader :assets
|
|
26
26
|
|
|
27
|
+
# @return [Plutonium::Wizard::Configuration] wizard subsystem configuration
|
|
28
|
+
attr_reader :wizards
|
|
29
|
+
|
|
27
30
|
# @return [Float] the current defaults version
|
|
28
31
|
attr_reader :defaults_version
|
|
29
32
|
|
|
@@ -54,6 +57,7 @@ module Plutonium
|
|
|
54
57
|
def initialize
|
|
55
58
|
@defaults_version = nil
|
|
56
59
|
@assets = AssetConfiguration.new
|
|
60
|
+
@wizards = Plutonium::Wizard::Configuration.new
|
|
57
61
|
|
|
58
62
|
@development = parse_boolean_env("PLUTONIUM_DEV")
|
|
59
63
|
@cache_discovery = !Rails.env.development?
|
|
@@ -127,7 +127,7 @@ module Plutonium
|
|
|
127
127
|
#
|
|
128
128
|
# @return [Hash] args to pass to `url_for`
|
|
129
129
|
#
|
|
130
|
-
def resource_url_args_for(*args, action: nil, parent: nil, association: nil, package: nil, interaction: nil, **kwargs)
|
|
130
|
+
def resource_url_args_for(*args, action: nil, parent: nil, association: nil, package: nil, interaction: nil, wizard: nil, **kwargs)
|
|
131
131
|
element = args.first
|
|
132
132
|
|
|
133
133
|
raise ArgumentError, "parent is required when using symbol association name" if element.is_a?(Symbol) && parent.nil?
|
|
@@ -138,6 +138,12 @@ module Plutonium
|
|
|
138
138
|
kwargs[:interactive_action] = interaction
|
|
139
139
|
end
|
|
140
140
|
|
|
141
|
+
if wizard
|
|
142
|
+
raise ArgumentError, "cannot pass both `wizard:` and `action:`" if action
|
|
143
|
+
action = wizard_action_type_for(element, step: kwargs[:step])
|
|
144
|
+
kwargs[:wizard_name] = wizard
|
|
145
|
+
end
|
|
146
|
+
|
|
141
147
|
# For nested resources, use named route helpers to avoid Rails param recall ambiguity
|
|
142
148
|
if parent.present?
|
|
143
149
|
assoc_name = if element.is_a?(Symbol)
|
|
@@ -194,6 +200,19 @@ module Plutonium
|
|
|
194
200
|
end
|
|
195
201
|
end
|
|
196
202
|
|
|
203
|
+
# Determine the wizard action type for the given element. Records → member,
|
|
204
|
+
# classes/symbols/nil → collection (wizards have no bulk variant). With no
|
|
205
|
+
# `step:`, target the bare LAUNCH action (which resolves the run and redirects
|
|
206
|
+
# to its current step); with a `step:`, target the stepped show action.
|
|
207
|
+
def wizard_action_type_for(element, step: nil)
|
|
208
|
+
member = !(element.is_a?(Class) || element.is_a?(Symbol) || element.nil?)
|
|
209
|
+
if step.nil?
|
|
210
|
+
member ? :launch_wizard_record_action : :launch_wizard_resource_action
|
|
211
|
+
else
|
|
212
|
+
member ? :wizard_record_action : :wizard_resource_action
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
|
|
197
216
|
def build_nested_resource_url_args(element, parent:, association_name:, route_config:, action: nil, **kwargs)
|
|
198
217
|
prefix = Plutonium::Routing::NESTED_ROUTE_PREFIX
|
|
199
218
|
is_singular = route_config[:route_type] == :resource
|
|
@@ -29,6 +29,7 @@ module Plutonium
|
|
|
29
29
|
include ConfigAttr
|
|
30
30
|
include InheritableConfigAttr
|
|
31
31
|
include Actions
|
|
32
|
+
include Wizards
|
|
32
33
|
include Sorting
|
|
33
34
|
include Scoping
|
|
34
35
|
include Search
|
|
@@ -120,6 +121,30 @@ module Plutonium
|
|
|
120
121
|
modal_size size
|
|
121
122
|
end
|
|
122
123
|
|
|
124
|
+
# show_in — how the :show page opens from a record link (table row,
|
|
125
|
+
# grid card). Unlike :new/:edit (which follow `modal_mode`), the show
|
|
126
|
+
# page is ALWAYS centered when shown in a modal, so this is just a
|
|
127
|
+
# modal/page switch — not a style.
|
|
128
|
+
#
|
|
129
|
+
# :page (default) — full-page navigation to the show route
|
|
130
|
+
# :modal — open the show page in a centered dialog
|
|
131
|
+
#
|
|
132
|
+
# The kanban board has its own `show_in` that overrides this per-board.
|
|
133
|
+
VALID_SHOW_IN = [:modal, :page].freeze
|
|
134
|
+
|
|
135
|
+
inheritable_config_attr :show_in
|
|
136
|
+
show_in :page
|
|
137
|
+
|
|
138
|
+
# Validated setter — raises on an unknown mode rather than silently
|
|
139
|
+
# falling back, matching the kanban board's `show_in`.
|
|
140
|
+
def self.show_in(value = :__not_set__)
|
|
141
|
+
return show_in_config if value == :__not_set__
|
|
142
|
+
unless VALID_SHOW_IN.include?(value)
|
|
143
|
+
raise ArgumentError, "show_in must be one of #{VALID_SHOW_IN.inspect}, got #{value.inspect}"
|
|
144
|
+
end
|
|
145
|
+
self.show_in_config = value
|
|
146
|
+
end
|
|
147
|
+
|
|
123
148
|
def initialize
|
|
124
149
|
super
|
|
125
150
|
end
|
|
@@ -33,6 +33,59 @@ module Plutonium
|
|
|
33
33
|
# filtering). Produced by #resolve_form_sections (a later task).
|
|
34
34
|
ResolvedSection = Struct.new(:section, :fields)
|
|
35
35
|
|
|
36
|
+
# First-section-wins ownership, shared by every layout resolver (the resource
|
|
37
|
+
# form via {#resolve_form_sections}, and the wizard's {StepAdapter} /
|
|
38
|
+
# {FieldImporter}). Each field is claimed by the FIRST explicit section that
|
|
39
|
+
# lists it, restricted to the currently-permitted `fields`; a listed field
|
|
40
|
+
# outside that set is simply skipped (never renders, never an error).
|
|
41
|
+
#
|
|
42
|
+
# @param layout [Array<Section>]
|
|
43
|
+
# @param fields [Array<Symbol,String>] the permitted field set, in order
|
|
44
|
+
# @return [Array(Hash, Array<Symbol>)] `[owner_by_field, leftover_fields]`
|
|
45
|
+
def self.assign_ownership(layout, fields)
|
|
46
|
+
fields = fields.map(&:to_sym)
|
|
47
|
+
known = fields.to_set
|
|
48
|
+
owner = {}
|
|
49
|
+
layout.each do |section|
|
|
50
|
+
next if section.ungrouped?
|
|
51
|
+
section.fields.map(&:to_sym).each { |f| owner[f] ||= section.key if known.include?(f) }
|
|
52
|
+
end
|
|
53
|
+
leftovers = fields.reject { |f| owner.key?(f) }
|
|
54
|
+
[owner, leftovers]
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# The canonical resolution: first-section-wins ownership, with unclaimed
|
|
58
|
+
# permitted fields falling into the (explicit, or a synthesized trailing)
|
|
59
|
+
# ungrouped bucket so nothing silently disappears. Every declared section is
|
|
60
|
+
# kept (empty ones are dropped at render). Shared by {#resolve_form_sections}
|
|
61
|
+
# and the wizard {StepAdapter}'s raw-layout path so the two never drift.
|
|
62
|
+
#
|
|
63
|
+
# @param layout [Array<Section>]
|
|
64
|
+
# @param fields [Array<Symbol,String>] the permitted field set, in order
|
|
65
|
+
# @return [Array<ResolvedSection>]
|
|
66
|
+
def self.resolve_sections(layout, fields)
|
|
67
|
+
owner, leftovers = assign_ownership(layout, fields)
|
|
68
|
+
|
|
69
|
+
resolved = layout.map do |section|
|
|
70
|
+
section_fields =
|
|
71
|
+
if section.ungrouped?
|
|
72
|
+
leftovers
|
|
73
|
+
else
|
|
74
|
+
section.fields.map(&:to_sym).select { |f| owner[f] == section.key }
|
|
75
|
+
end
|
|
76
|
+
ResolvedSection.new(section:, fields: section_fields)
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
unless layout.any?(&:ungrouped?)
|
|
80
|
+
resolved.push(ResolvedSection.new(
|
|
81
|
+
section: Section.new(key: UNGROUPED_KEY, fields: [].freeze, options: {}.freeze),
|
|
82
|
+
fields: leftovers
|
|
83
|
+
))
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
resolved
|
|
87
|
+
end
|
|
88
|
+
|
|
36
89
|
# Collects section/ungrouped calls from a form_layout block in order.
|
|
37
90
|
class Builder
|
|
38
91
|
attr_reader :sections
|
|
@@ -102,41 +155,7 @@ module Plutonium
|
|
|
102
155
|
layout = defined_form_layout
|
|
103
156
|
return nil unless layout
|
|
104
157
|
|
|
105
|
-
|
|
106
|
-
known = resource_fields.to_set
|
|
107
|
-
|
|
108
|
-
# First-section-wins assignment: each field is claimed by the first
|
|
109
|
-
# section that lists it. A field a section lists but that isn't in the
|
|
110
|
-
# currently-permitted set (policy, per-action, entity scoping, nesting)
|
|
111
|
-
# is simply skipped — it never renders and is never an error.
|
|
112
|
-
owner = {}
|
|
113
|
-
layout.each do |section|
|
|
114
|
-
next if section.ungrouped?
|
|
115
|
-
section.fields.each do |f|
|
|
116
|
-
owner[f] ||= section.key if known.include?(f)
|
|
117
|
-
end
|
|
118
|
-
end
|
|
119
|
-
leftovers = resource_fields.reject { |f| owner.key?(f) }
|
|
120
|
-
|
|
121
|
-
resolved = layout.map do |section|
|
|
122
|
-
fields =
|
|
123
|
-
if section.ungrouped?
|
|
124
|
-
leftovers
|
|
125
|
-
else
|
|
126
|
-
section.fields.select { |f| owner[f] == section.key }
|
|
127
|
-
end
|
|
128
|
-
ResolvedSection.new(section:, fields:)
|
|
129
|
-
end
|
|
130
|
-
|
|
131
|
-
unless layout.any?(&:ungrouped?)
|
|
132
|
-
implicit = ResolvedSection.new(
|
|
133
|
-
section: Section.new(key: UNGROUPED_KEY, fields: [].freeze, options: {}.freeze),
|
|
134
|
-
fields: leftovers
|
|
135
|
-
)
|
|
136
|
-
resolved.push(implicit)
|
|
137
|
-
end
|
|
138
|
-
|
|
139
|
-
resolved
|
|
158
|
+
FormLayout.resolve_sections(layout, resource_fields)
|
|
140
159
|
end
|
|
141
160
|
end
|
|
142
161
|
end
|