plutonium 0.33.1 → 0.34.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.
Files changed (143) hide show
  1. checksums.yaml +4 -4
  2. data/# Plutonium: The pre-alpha demo.md +4 -2
  3. data/.claude/skills/assets/SKILL.md +416 -0
  4. data/.claude/skills/connect-resource/SKILL.md +112 -0
  5. data/.claude/skills/controller/SKILL.md +302 -0
  6. data/.claude/skills/create-resource/SKILL.md +240 -0
  7. data/.claude/skills/definition/SKILL.md +218 -0
  8. data/.claude/skills/definition-actions/SKILL.md +386 -0
  9. data/.claude/skills/definition-fields/SKILL.md +474 -0
  10. data/.claude/skills/definition-query/SKILL.md +334 -0
  11. data/.claude/skills/forms/SKILL.md +439 -0
  12. data/.claude/skills/installation/SKILL.md +300 -0
  13. data/.claude/skills/interaction/SKILL.md +382 -0
  14. data/.claude/skills/model/SKILL.md +267 -0
  15. data/.claude/skills/model-features/SKILL.md +286 -0
  16. data/.claude/skills/nested-resources/SKILL.md +274 -0
  17. data/.claude/skills/package/SKILL.md +191 -0
  18. data/.claude/skills/policy/SKILL.md +352 -0
  19. data/.claude/skills/portal/SKILL.md +400 -0
  20. data/.claude/skills/resource/SKILL.md +281 -0
  21. data/.claude/skills/rodauth/SKILL.md +452 -0
  22. data/.claude/skills/views/SKILL.md +563 -0
  23. data/Appraisals +46 -4
  24. data/CHANGELOG.md +32 -1
  25. data/app/assets/plutonium.css +2 -2
  26. data/config/brakeman.ignore +239 -0
  27. data/config/initializers/action_policy.rb +1 -1
  28. data/docs/.vitepress/config.ts +132 -47
  29. data/docs/concepts/architecture.md +226 -0
  30. data/docs/concepts/auto-detection.md +254 -0
  31. data/docs/concepts/index.md +61 -0
  32. data/docs/concepts/packages-portals.md +304 -0
  33. data/docs/concepts/resources.md +224 -0
  34. data/docs/cookbook/blog.md +412 -0
  35. data/docs/cookbook/index.md +289 -0
  36. data/docs/cookbook/saas.md +481 -0
  37. data/docs/getting-started/index.md +56 -0
  38. data/docs/getting-started/installation.md +146 -0
  39. data/docs/getting-started/tutorial/01-setup.md +118 -0
  40. data/docs/getting-started/tutorial/02-first-resource.md +180 -0
  41. data/docs/getting-started/tutorial/03-authentication.md +246 -0
  42. data/docs/getting-started/tutorial/04-authorization.md +170 -0
  43. data/docs/getting-started/tutorial/05-custom-actions.md +202 -0
  44. data/docs/getting-started/tutorial/06-nested-resources.md +147 -0
  45. data/docs/getting-started/tutorial/07-customizing-ui.md +254 -0
  46. data/docs/getting-started/tutorial/index.md +64 -0
  47. data/docs/guides/adding-resources.md +420 -0
  48. data/docs/guides/authentication.md +551 -0
  49. data/docs/guides/authorization.md +468 -0
  50. data/docs/guides/creating-packages.md +380 -0
  51. data/docs/guides/custom-actions.md +523 -0
  52. data/docs/guides/index.md +45 -0
  53. data/docs/guides/multi-tenancy.md +302 -0
  54. data/docs/guides/nested-resources.md +411 -0
  55. data/docs/guides/search-filtering.md +266 -0
  56. data/docs/guides/theming.md +321 -0
  57. data/docs/index.md +67 -26
  58. data/docs/public/CLAUDE.md +64 -21
  59. data/docs/reference/assets/index.md +496 -0
  60. data/docs/reference/controller/index.md +363 -0
  61. data/docs/reference/definition/actions.md +400 -0
  62. data/docs/reference/definition/fields.md +350 -0
  63. data/docs/reference/definition/index.md +252 -0
  64. data/docs/reference/definition/query.md +342 -0
  65. data/docs/reference/generators/index.md +469 -0
  66. data/docs/reference/index.md +49 -0
  67. data/docs/reference/interaction/index.md +445 -0
  68. data/docs/reference/model/features.md +248 -0
  69. data/docs/reference/model/index.md +219 -0
  70. data/docs/reference/policy/index.md +385 -0
  71. data/docs/reference/portal/index.md +382 -0
  72. data/docs/reference/views/forms.md +396 -0
  73. data/docs/reference/views/index.md +479 -0
  74. data/gemfiles/rails_7.gemfile +9 -2
  75. data/gemfiles/rails_7.gemfile.lock +146 -111
  76. data/gemfiles/rails_8.0.gemfile +20 -0
  77. data/gemfiles/rails_8.0.gemfile.lock +417 -0
  78. data/gemfiles/rails_8.1.gemfile +20 -0
  79. data/gemfiles/rails_8.1.gemfile.lock +419 -0
  80. data/lib/generators/pu/gem/dotenv/templates/.env +2 -0
  81. data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +3 -1
  82. data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +13 -16
  83. data/lib/generators/pu/pkg/portal/USAGE +65 -0
  84. data/lib/generators/pu/pkg/portal/portal_generator.rb +22 -9
  85. data/lib/generators/pu/res/conn/USAGE +71 -0
  86. data/lib/generators/pu/res/model/USAGE +106 -110
  87. data/lib/generators/pu/res/model/templates/model.rb.tt +6 -2
  88. data/lib/generators/pu/res/scaffold/USAGE +85 -0
  89. data/lib/generators/pu/rodauth/install_generator.rb +2 -6
  90. data/lib/generators/pu/rodauth/templates/config/initializers/url_options.rb +17 -0
  91. data/lib/generators/pu/skills/sync/USAGE +14 -0
  92. data/lib/generators/pu/skills/sync/sync_generator.rb +66 -0
  93. data/lib/plutonium/action_policy/sti_policy_lookup.rb +1 -1
  94. data/lib/plutonium/core/controller.rb +2 -2
  95. data/lib/plutonium/interaction/base.rb +1 -0
  96. data/lib/plutonium/package/engine.rb +2 -2
  97. data/lib/plutonium/query/adhoc_block.rb +6 -2
  98. data/lib/plutonium/query/model_scope.rb +1 -1
  99. data/lib/plutonium/railtie.rb +4 -0
  100. data/lib/plutonium/resource/controllers/crud_actions/index_action.rb +1 -1
  101. data/lib/plutonium/resource/query_object.rb +38 -8
  102. data/lib/plutonium/ui/table/components/scopes_bar.rb +39 -34
  103. data/lib/plutonium/version.rb +1 -1
  104. data/lib/tasks/release.rake +19 -4
  105. data/package.json +1 -1
  106. metadata +76 -39
  107. data/brakeman.ignore +0 -28
  108. data/docs/api-examples.md +0 -49
  109. data/docs/guide/claude-code-guide.md +0 -74
  110. data/docs/guide/deep-dive/authorization.md +0 -189
  111. data/docs/guide/deep-dive/multitenancy.md +0 -256
  112. data/docs/guide/deep-dive/resources.md +0 -390
  113. data/docs/guide/getting-started/01-installation.md +0 -165
  114. data/docs/guide/index.md +0 -28
  115. data/docs/guide/introduction/01-what-is-plutonium.md +0 -211
  116. data/docs/guide/introduction/02-core-concepts.md +0 -440
  117. data/docs/guide/tutorial/01-project-setup.md +0 -75
  118. data/docs/guide/tutorial/02-creating-a-feature-package.md +0 -45
  119. data/docs/guide/tutorial/03-defining-resources.md +0 -90
  120. data/docs/guide/tutorial/04-creating-a-portal.md +0 -101
  121. data/docs/guide/tutorial/05-customizing-the-ui.md +0 -128
  122. data/docs/guide/tutorial/06-adding-custom-actions.md +0 -101
  123. data/docs/guide/tutorial/07-implementing-authorization.md +0 -90
  124. data/docs/markdown-examples.md +0 -85
  125. data/docs/modules/action.md +0 -244
  126. data/docs/modules/authentication.md +0 -236
  127. data/docs/modules/configuration.md +0 -599
  128. data/docs/modules/controller.md +0 -443
  129. data/docs/modules/core.md +0 -316
  130. data/docs/modules/definition.md +0 -1308
  131. data/docs/modules/display.md +0 -759
  132. data/docs/modules/form.md +0 -495
  133. data/docs/modules/generator.md +0 -400
  134. data/docs/modules/index.md +0 -167
  135. data/docs/modules/interaction.md +0 -642
  136. data/docs/modules/package.md +0 -151
  137. data/docs/modules/policy.md +0 -176
  138. data/docs/modules/portal.md +0 -710
  139. data/docs/modules/query.md +0 -297
  140. data/docs/modules/resource_record.md +0 -618
  141. data/docs/modules/routing.md +0 -690
  142. data/docs/modules/table.md +0 -301
  143. data/docs/modules/ui.md +0 -631
@@ -1,301 +0,0 @@
1
- ---
2
- title: Table Module
3
- ---
4
-
5
- # Table Module
6
-
7
- The Table module is a powerful system for creating data tables in Plutonium. It leverages `Phlexi::Table` to provide a rich set of features including smart column rendering, pagination, sorting, filtering, and search. It's designed to work seamlessly with Plutonium's resource definitions to help you build complex data displays with minimal effort.
8
-
9
- ::: tip Architecture
10
- The Table module lives in `lib/plutonium/ui/table/` and is composed of several key parts:
11
- - **`Plutonium::UI::Table::Resource`**: The primary component for rendering resource-based tables.
12
- - **Components**: UI elements like search bars, scope selectors, and pagination controls.
13
- - **Themes**: Centralized styling for a consistent look and feel.
14
- :::
15
-
16
- ## Getting Started: Defining a Table
17
-
18
- Everything about a table—its columns, filters, and behaviors—is defined within a resource definition file. You can use `display`, `column`, or `field` to define what data to show.
19
-
20
- Here's a basic example for a `Post` resource:
21
-
22
- ```ruby
23
- # app/definitions/post_definition.rb
24
- class PostDefinition < Plutonium::Resource::Definition
25
- # Use `display` or `column` to define table columns.
26
- display :author, as: :association
27
- display :published_at, as: :datetime
28
- display :status, as: :badge
29
- display :actions, as: :actions, align: :right
30
-
31
- # Define sorting
32
- sort :title
33
- sort :published_at
34
-
35
- # Define default sort (newest first)
36
- default_sort :created_at, :desc
37
-
38
- # Enable search
39
- search do |scope, query|
40
- scope.where("title ILIKE ?", "%#{query}%")
41
- end
42
-
43
- # Define filters
44
- filter :published, with: Plutonium::Query::Filters::Text, predicate: :eq
45
- filter :author, with: Plutonium::Query::Filters::Text, predicate: :eq
46
-
47
- # Define query scopes
48
- scope :published
49
- scope :draft
50
- end
51
- ```
52
-
53
- This configuration is all you need to render a feature-rich table for your posts.
54
-
55
- ## Configuring Columns
56
-
57
- Columns are the heart of your table. Plutonium offers flexible ways to configure them.
58
-
59
- ### Column Types
60
-
61
- You can render data in various formats using the `as:` option:
62
-
63
- ```ruby
64
- column :name, as: :string
65
- column :email, as: :email
66
- column :website, as: :link
67
- column :published_at, as: :datetime
68
- column :is_active, as: :boolean
69
- column :priority, as: :badge
70
- column :profile_picture, as: :attachment
71
- column :metadata, as: :key_value_store
72
- ```
73
-
74
- ### Alignment
75
-
76
- Control column alignment with the `align:` option.
77
-
78
- ```ruby
79
- column :title, align: :start # Left-aligned (default)
80
- column :price, align: :end # Right-aligned
81
- column :status, align: :center # Center-aligned
82
- ```
83
-
84
- ### Custom Column Rendering
85
-
86
- For complete control over a column's output, provide a block. The block receives a wrapped record object.
87
-
88
- ```ruby
89
- class PostDefinition < Plutonium::Resource::Definition
90
- # Basic custom rendering with a block
91
- column :full_name do |wrapped_record|
92
- # `unwrapped` gives you the original AR record
93
- record = wrapped_record.unwrapped
94
- "#{record.first_name} #{record.last_name}"
95
- end
96
-
97
- # Render a custom component for more complex UI
98
- column :status do |wrapped_record|
99
- # The `field` method provides access to the field's value and definition
100
- field = wrapped_record.field(:status)
101
- render StatusBadgeComponent.new(field.value)
102
- end
103
- end
104
- ```
105
-
106
- ### Conditional Columns
107
-
108
- You can show or hide columns dynamically using the `condition` option. It accepts a lambda that is evaluated in the view context.
109
-
110
- ```ruby
111
- # Show a column only in the development environment
112
- column :debug_info, condition: -> { Rails.env.development? }
113
-
114
- # Show a column based on user permissions
115
- column :admin_notes, condition: -> { current_user.admin? }
116
- ```
117
-
118
- ::: warning Security
119
- Use `condition` for display logic, not for security. To control data visibility, you should filter `permitted_attributes_for_read` within your authorization policies.
120
- :::
121
-
122
- ## Searching and Filtering
123
-
124
- Plutonium makes it easy to add powerful search and filtering capabilities to your tables.
125
-
126
- ### Search
127
-
128
- Define your search logic with the `search` method in your resource definition. The search bar will appear automatically.
129
-
130
- ```ruby
131
- class PostDefinition < Plutonium::Resource::Definition
132
- # Simple search on a single field
133
- search do |scope, search_term|
134
- scope.where("title ILIKE ?", "%#{search_term}%")
135
- end
136
-
137
- # More complex search across multiple fields and associations
138
- search do |scope, search_term|
139
- scope.joins(:author)
140
- .where(
141
- "posts.title ILIKE :q OR posts.content ILIKE :q OR users.name ILIKE :q",
142
- q: "%#{search_term}%"
143
- )
144
- end
145
- end
146
- ```
147
-
148
- ### Filters
149
-
150
- Declare filters using the `filter` method. Currently, Plutonium provides the Text filter with various predicates.
151
-
152
- ```ruby
153
- class PostDefinition < Plutonium::Resource::Definition
154
- # Text filter with exact match
155
- filter :status, with: Plutonium::Query::Filters::Text, predicate: :eq
156
-
157
- # Text filter with contains matching
158
- filter :title, with: Plutonium::Query::Filters::Text, predicate: :contains
159
-
160
- # Text filter with starts_with matching
161
- filter :category, with: Plutonium::Query::Filters::Text, predicate: :starts_with
162
-
163
- # Custom filter with lambda
164
- filter :published, with: ->(scope, value) {
165
- value ? scope.where.not(published_at: nil) : scope.where(published_at: nil)
166
- }
167
- end
168
- ```
169
-
170
- Available Text filter predicates include: `:eq`, `:not_eq`, `:matches`, `:not_matches`, `:starts_with`, `:ends_with`, `:contains`, `:not_contains`.
171
-
172
- ## Query Scopes
173
-
174
- Scopes allow users to apply predefined queries with a single click. Define them using the `scope` method, which can reference an existing model scope or a new lambda.
175
-
176
- ```ruby
177
- class PostDefinition < Plutonium::Resource::Definition
178
- # Reference existing scopes from the Post model
179
- scope :published
180
- scope :featured
181
-
182
- # Define a custom scope with a lambda
183
- scope :recent, -> { where("created_at > ?", 1.week.ago) }
184
-
185
- # Set a default scope
186
- scope :active, default: true
187
- end
188
- ```
189
- A scopes bar will automatically be displayed above the table.
190
-
191
- ## Sorting
192
-
193
- Enable sorting on columns by defining a `sort` rule. Columns automatically become sortable when a sort definition exists for them.
194
-
195
- ```ruby
196
- class PostDefinition < Plutonium::Resource::Definition
197
- # Define sort rules for columns
198
- sort :title
199
- sort :created_at
200
- sort :updated_at
201
-
202
- # Custom sorting logic
203
- sort :author_name, using: "users.name" do |scope, direction:|
204
- scope.joins(:author).order("users.name #{direction}")
205
- end
206
-
207
- # Default sort when no user sorting is applied
208
- default_sort :created_at, :desc # Simple form
209
- # or with a block for complex sorting:
210
- # default_sort { |scope| scope.order(featured: :desc, created_at: :desc) }
211
- end
212
- ```
213
-
214
- Plutonium's tables support both tri-state and multi-column sorting, providing flexible data exploration.
215
-
216
- * **Tri-state Sorting**: Clicking a column header cycles through ascending (`ASC`), descending (`DESC`), and unsorted states for that column.
217
- * **Multi-column Sorting**: You can apply sorting to multiple columns. Simply click on the headers of the columns you wish to sort by. The order in which you select them determines their priority. An indicator next to the column title shows the sort order and priority.
218
-
219
- ## Pagination
220
-
221
- Pagination is handled automatically by the excellent [Pagy](https://github.com/ddnexus/pagy) gem. In your controller, the `pagy` helper method prepares your records for pagination.
222
-
223
- ```ruby
224
- # In your controller (usually handled by Plutonium::Controller::CrudActions)
225
- @pagy, @resource_records = pagy(current_authorized_scope)
226
- ```
227
-
228
- The table component renders pagination controls and an info bar, allowing users to navigate through pages and change the number of items per page.
229
-
230
- ## Actions
231
-
232
- Actions defined on your resource will automatically appear in the `actions` column for each row.
233
-
234
- ```ruby
235
- class PostDefinition < Plutonium::Resource::Definition
236
- # Standard CRUD actions are available by default
237
- # action :show
238
- # action :edit
239
- # action :destroy
240
-
241
- # Add custom actions
242
- action :publish, interaction: PublishPostInteraction
243
- action :archive, interaction: ArchivePostInteraction
244
- end
245
- ```
246
-
247
- Plutonium checks the user's permissions for each action and only displays the ones they are allowed to perform.
248
-
249
- ## Customization
250
-
251
- ### Overriding the Table View
252
-
253
- For deep customization, you can define a nested `Table` class within your resource definition. This allows you to override any part of the table rendering process.
254
-
255
- ```ruby
256
- class PostDefinition < Plutonium::Resource::Definition
257
- # Define a custom table class
258
- class Table < Plutonium::UI::Table::Resource
259
- private
260
-
261
- # Customize the footer
262
- def render_footer
263
- div(class: "custom-footer") do
264
- super # Render the original footer (pagination, etc.)
265
- render_custom_stats
266
- end
267
- end
268
-
269
- def render_custom_stats
270
- div(class: "mt-4 text-sm text-gray-500") do
271
- "Total Posts: #{collection.size}"
272
- end
273
- end
274
- end
275
- end
276
- ```
277
-
278
- ### Empty State
279
-
280
- When a query returns no results, the table displays a helpful message. You can customize this by overriding `render_empty_card`.
281
-
282
- ```ruby
283
- class PostDefinition < Plutonium::Resource::Definition
284
- class Table < Plutonium::UI::Table::Resource
285
- private
286
-
287
- def render_empty_card
288
- EmptyCard("No posts were found.") {
289
- # Optionally, add a call to action
290
- if current_policy.allowed_to?(:create?)
291
- # ... render a "Create Post" button
292
- end
293
- }
294
- end
295
- end
296
- end
297
- ```
298
-
299
- ### Theming
300
-
301
- The table's appearance is controlled by a central theme. You can inspect `lib/plutonium/ui/table/theme.rb` and `lib/plutonium/ui/table/display_theme.rb` to see the default Tailwind CSS classes and override them if needed.