plutonium 0.15.6 → 0.15.7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/assets/plutonium.css +1 -1
- data/app/assets/plutonium.js +25 -11
- data/app/assets/plutonium.js.map +2 -2
- data/app/assets/plutonium.min.js +4 -4
- data/app/assets/plutonium.min.js.map +3 -3
- data/app/views/layouts/rodauth.html.erb +2 -2
- data/docs/guide/getting-started/installation.md +2 -1
- data/docs/guide/getting-started/resources.md +8 -12
- data/docs/public/templates/plutonium.rb +8 -0
- data/lib/generators/pu/core/assets/assets_generator.rb +1 -1
- data/lib/generators/pu/eject/layout/layout_generator.rb +3 -3
- data/lib/generators/pu/eject/shell/shell_generator.rb +3 -3
- data/lib/generators/pu/gem/dotenv/dotenv_generator.rb +1 -1
- data/lib/generators/pu/gem/letter_opener/letter_opener_generator.rb +21 -0
- data/lib/generators/pu/gem/redis/redis_generator.rb +0 -2
- data/lib/generators/pu/gem/standard/standard_generator.rb +19 -0
- data/lib/generators/pu/lib/plutonium_generators/generator.rb +1 -1
- data/lib/generators/pu/res/conn/conn_generator.rb +1 -1
- data/lib/plutonium/definition/actions.rb +6 -2
- data/lib/plutonium/definition/base.rb +1 -0
- data/lib/plutonium/definition/nested_inputs.rb +19 -0
- data/lib/plutonium/resource/controller.rb +1 -1
- data/lib/plutonium/resource/controllers/interactive_actions.rb +1 -1
- data/lib/plutonium/resource/controllers/presentable.rb +1 -5
- data/lib/plutonium/ui/block.rb +13 -0
- data/lib/plutonium/ui/component/kit.rb +10 -0
- data/lib/plutonium/ui/display/resource.rb +29 -11
- data/lib/plutonium/ui/display/theme.rb +1 -1
- data/lib/plutonium/ui/dyna_frame/content.rb +2 -2
- data/lib/plutonium/ui/dyna_frame/host.rb +20 -0
- data/lib/plutonium/ui/form/concerns/renders_nested_resource_fields.rb +282 -0
- data/lib/plutonium/ui/form/resource.rb +39 -29
- data/lib/plutonium/ui/form/theme.rb +1 -1
- data/lib/plutonium/ui/frame_navigator_panel.rb +53 -0
- data/lib/plutonium/ui/panel.rb +63 -0
- data/lib/plutonium/ui/skeleton_table.rb +29 -0
- data/lib/plutonium/ui/table/resource.rb +1 -1
- data/lib/plutonium/version.rb +1 -1
- data/src/js/controllers/frame_navigator_controller.js +25 -8
- data/src/js/controllers/nested_resource_form_fields_controller.js +2 -2
- metadata +11 -3
- data/lib/generators/pu/gem/redis/templates/.keep +0 -0
@@ -12,8 +12,8 @@
|
|
12
12
|
<%= yield %>
|
13
13
|
</div>
|
14
14
|
</div>
|
15
|
-
<div class="mt-4 flex items-center font-medium text-
|
15
|
+
<div class="mt-4 flex items-center font-medium text-secondary-600 dark:text-secondary-400 hover:underline">
|
16
16
|
<%= render_icon "outline/home" %>
|
17
|
-
<%= link_to "Home", root_path, class: "font-medium text-
|
17
|
+
<%= link_to "Home", root_path, class: "font-medium text-secondary-600 dark:text-secondary-400" %>
|
18
18
|
</div>
|
19
19
|
<% end %>
|
@@ -3,6 +3,7 @@
|
|
3
3
|
::: tip VERSION REQUIREMENTS
|
4
4
|
- Ruby 3.2.2 or higher
|
5
5
|
- Rails 7.1 or higher
|
6
|
+
- Node.js and Yarn
|
6
7
|
:::
|
7
8
|
|
8
9
|
## Quick Start
|
@@ -151,7 +152,7 @@ bin/importmap pin @radioactive-labs/plutonium
|
|
151
152
|
```
|
152
153
|
|
153
154
|
```bash [esbuild]
|
154
|
-
|
155
|
+
yarn add @radioactive-labs/plutonium
|
155
156
|
```
|
156
157
|
:::
|
157
158
|
|
@@ -17,7 +17,8 @@ Resources are the core building blocks of a Plutonium application. A resource re
|
|
17
17
|
The fastest way to create a resource is using the scaffold generator:
|
18
18
|
|
19
19
|
```bash
|
20
|
-
rails generate pu:res:scaffold Blog user:belongs_to
|
20
|
+
rails generate pu:res:scaffold Blog user:belongs_to \
|
21
|
+
title:string content:text 'published_at:datetime?'
|
21
22
|
```
|
22
23
|
|
23
24
|
This generates several files, including:
|
@@ -40,11 +41,11 @@ class BlogPolicy < Plutonium::Resource::Policy
|
|
40
41
|
end
|
41
42
|
|
42
43
|
def permitted_attributes_for_create
|
43
|
-
%i[user title content
|
44
|
+
%i[user title content published_at]
|
44
45
|
end
|
45
46
|
|
46
47
|
def permitted_attributes_for_read
|
47
|
-
%i[user title content
|
48
|
+
%i[user title content published_at]
|
48
49
|
end
|
49
50
|
end
|
50
51
|
```
|
@@ -83,12 +84,12 @@ end
|
|
83
84
|
class BlogDefinition < Plutonium::Resource::Definition
|
84
85
|
# Customize how fields are displayed
|
85
86
|
display :title, class: "col-span-full"
|
86
|
-
display :content do |f|
|
87
|
+
display :content, class: "col-span-full" do |f|
|
87
88
|
f.text_tag class: "prose dark:prose-invert"
|
88
89
|
end
|
89
90
|
|
90
91
|
# Custom column display in tables
|
91
|
-
column :
|
92
|
+
column :published_at, align: :end
|
92
93
|
end
|
93
94
|
```
|
94
95
|
:::
|
@@ -140,7 +141,6 @@ module Blogs
|
|
140
141
|
|
141
142
|
def execute
|
142
143
|
if resource.update(
|
143
|
-
state: "published",
|
144
144
|
published_at: publish_date
|
145
145
|
)
|
146
146
|
succeed(resource)
|
@@ -175,20 +175,16 @@ class BlogDefinition < Plutonium::Resource::Definition
|
|
175
175
|
end
|
176
176
|
|
177
177
|
# Add filters
|
178
|
-
filter :state,
|
179
|
-
with: SelectFilter,
|
180
|
-
choices: %w[draft published]
|
181
|
-
|
182
178
|
filter :published_at,
|
183
179
|
with: DateFilter,
|
184
180
|
predicate: :gteq
|
185
181
|
|
186
182
|
# Add scopes
|
187
183
|
scope :published do |scope|
|
188
|
-
where(
|
184
|
+
scope.where.not(published_at: nil)
|
189
185
|
end
|
190
186
|
scope :draft do |scope|
|
191
|
-
where(
|
187
|
+
scope.where(published_at: nil)
|
192
188
|
end
|
193
189
|
|
194
190
|
# Configure sorting
|
@@ -15,6 +15,14 @@ after_bundle do
|
|
15
15
|
git add: "."
|
16
16
|
git commit: %( -m 'add annotate' )
|
17
17
|
|
18
|
+
generate "pu:gem:standard"
|
19
|
+
git add: "."
|
20
|
+
git commit: %( -m 'add standardrb' )
|
21
|
+
|
22
|
+
generate "pu:gem:letter_opener"
|
23
|
+
git add: "."
|
24
|
+
git commit: %( -m 'add letter_opener' )
|
25
|
+
|
18
26
|
generate "pu:core:assets"
|
19
27
|
git add: "."
|
20
28
|
git commit: %( -m 'integrate assets' )
|
@@ -15,7 +15,7 @@ module Pu
|
|
15
15
|
class_option :rodauth, type: :boolean
|
16
16
|
|
17
17
|
def start
|
18
|
-
destination_dir = (
|
18
|
+
destination_dir = (destination_portal == "main_app") ? "app/views/" : "packages/#{destination_portal}/app/views/"
|
19
19
|
[
|
20
20
|
"layouts/resource.html.erb"
|
21
21
|
].each do |file|
|
@@ -27,8 +27,8 @@ module Pu
|
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
-
def
|
31
|
-
@
|
30
|
+
def destination_portal
|
31
|
+
@destination_portal || select_portal(options[:dest], msg: "Select destination portal")
|
32
32
|
end
|
33
33
|
|
34
34
|
def copy_file(source_path, destination_path)
|
@@ -14,7 +14,7 @@ module Pu
|
|
14
14
|
class_option :dest, type: :string
|
15
15
|
|
16
16
|
def start
|
17
|
-
destination_dir = (
|
17
|
+
destination_dir = (destination_portal == "main_app") ? "app/views/" : "packages/#{destination_portal}/app/views"
|
18
18
|
[
|
19
19
|
"plutonium/_resource_header.html.erb",
|
20
20
|
"plutonium/_resource_sidebar.html.erb"
|
@@ -27,8 +27,8 @@ module Pu
|
|
27
27
|
|
28
28
|
private
|
29
29
|
|
30
|
-
def
|
31
|
-
@
|
30
|
+
def destination_portal
|
31
|
+
@destination_portal || select_portal(options[:dest], msg: "Select destination portal")
|
32
32
|
end
|
33
33
|
|
34
34
|
def copy_file(source_path, destination_path)
|
@@ -21,7 +21,7 @@ module Pu
|
|
21
21
|
|
22
22
|
gitignore "!/.env.template", "!/.env.local.template", "!/.env"
|
23
23
|
|
24
|
-
insert_into_file "Gemfile", "\ngem \"dotenv\", :
|
24
|
+
insert_into_file "Gemfile", "\ngem \"dotenv\", groups: %i[development test]\n", after: /^gem ["']rails["'].*\n/
|
25
25
|
bundle!
|
26
26
|
end
|
27
27
|
rescue => e
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../lib/plutonium_generators"
|
4
|
+
|
5
|
+
module Pu
|
6
|
+
module Gem
|
7
|
+
class LetterOpenerGenerator < Rails::Generators::Base
|
8
|
+
include PlutoniumGenerators::Generator
|
9
|
+
|
10
|
+
desc "Set up letter_opener"
|
11
|
+
|
12
|
+
def start
|
13
|
+
bundle "letter_opener", group: :development
|
14
|
+
environment "config.action_mailer.delivery_method = :letter_opener", env: :development
|
15
|
+
environment "config.action_mailer.perform_deliveries = true", env: :development
|
16
|
+
rescue => e
|
17
|
+
exception "#{self.class} failed:", e
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../lib/plutonium_generators"
|
4
|
+
|
5
|
+
module Pu
|
6
|
+
module Gem
|
7
|
+
class StandardGenerator < Rails::Generators::Base
|
8
|
+
include PlutoniumGenerators::Generator
|
9
|
+
|
10
|
+
desc "Set up standardrb"
|
11
|
+
|
12
|
+
def start
|
13
|
+
bundle "standardrb"
|
14
|
+
rescue => e
|
15
|
+
exception "#{self.class} failed:", e
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -22,7 +22,7 @@ module Pu
|
|
22
22
|
error "No resources found" if available_resources.blank?
|
23
23
|
selected_resources = prompt.multi_select("Select resources", available_resources)
|
24
24
|
|
25
|
-
@app_namespace =
|
25
|
+
@app_namespace = select_portal.camelize
|
26
26
|
|
27
27
|
selected_resources.each do |resource|
|
28
28
|
@resource_class = resource
|
@@ -14,8 +14,12 @@ module Plutonium
|
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
17
|
-
def action(name, **)
|
18
|
-
instance_defined_actions[name] =
|
17
|
+
def action(name, interaction: nil, **)
|
18
|
+
instance_defined_actions[name] = if interaction
|
19
|
+
Plutonium::Action::Interactive::Factory.create(name, interaction:, **)
|
20
|
+
else
|
21
|
+
Plutonium::Action::Simple.new(name, **)
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
25
|
def defined_actions
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module Definition
|
3
|
+
module NestedInputs
|
4
|
+
extend ActiveSupport::Concern
|
5
|
+
|
6
|
+
included do
|
7
|
+
defineable_prop :nested_input
|
8
|
+
|
9
|
+
# def self.nested_input(name, with: nil, **)
|
10
|
+
# defined_nested_inputs[name] = {}
|
11
|
+
# end
|
12
|
+
|
13
|
+
# def nested_input(name, with: nil, **)
|
14
|
+
# instance_defined_nested_inputs[name] = {}
|
15
|
+
# end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -59,7 +59,7 @@ module Plutonium
|
|
59
59
|
# Returns the submitted resource parameters
|
60
60
|
# @return [Hash] The submitted resource parameters
|
61
61
|
def submitted_resource_params
|
62
|
-
@submitted_resource_params ||= build_form(resource_class.new).extract_input(params)[resource_param_key.to_sym]
|
62
|
+
@submitted_resource_params ||= build_form(resource_class.new).extract_input(params, view_context:)[resource_param_key.to_sym]
|
63
63
|
end
|
64
64
|
|
65
65
|
# Returns the resource parameters, including scoped and parent parameters
|
@@ -232,7 +232,7 @@ module Plutonium
|
|
232
232
|
@submitted_interaction_params ||= current_interactive_action
|
233
233
|
.interaction
|
234
234
|
.build_form(nil)
|
235
|
-
.extract_input(params)[:interaction]
|
235
|
+
.extract_input(params, view_context:)[:interaction]
|
236
236
|
end
|
237
237
|
|
238
238
|
def redirect_url_after_action_on(resource_record_or_resource_class)
|
@@ -5,7 +5,7 @@ module Plutonium
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
helper_method :presentable_attributes
|
8
|
+
helper_method :presentable_attributes
|
9
9
|
helper_method :build_form, :build_detail, :build_collection
|
10
10
|
end
|
11
11
|
|
@@ -31,10 +31,6 @@ module Plutonium
|
|
31
31
|
def build_form(record = resource_record)
|
32
32
|
current_definition.form_class.new(record, resource_fields: presentable_attributes, resource_definition: current_definition)
|
33
33
|
end
|
34
|
-
|
35
|
-
def present_associations?
|
36
|
-
current_parent.nil?
|
37
|
-
end
|
38
34
|
end
|
39
35
|
end
|
40
36
|
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module UI
|
3
|
+
class Block < Plutonium::UI::Component::Base
|
4
|
+
def view_template(&)
|
5
|
+
raise ArgumentError, "Block requires a content block" unless block_given?
|
6
|
+
|
7
|
+
div class: "relative bg-white dark:bg-gray-800 shadow-md sm:rounded-lg my-3" do
|
8
|
+
yield
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -10,6 +10,16 @@ module Plutonium
|
|
10
10
|
|
11
11
|
def Breadcrumbs(...) = render Plutonium::UI::Breadcrumbs.new(...)
|
12
12
|
|
13
|
+
def SkeletonTable(...) = render Plutonium::UI::SkeletonTable.new(...)
|
14
|
+
|
15
|
+
def Block(...) = render Plutonium::UI::Block.new(...)
|
16
|
+
|
17
|
+
def Panel(...) = render Plutonium::UI::Panel.new(...)
|
18
|
+
|
19
|
+
def FrameNavigatorPanel(...) = render Plutonium::UI::FrameNavigatorPanel.new(...)
|
20
|
+
|
21
|
+
def DynaFrameHost(...) = render Plutonium::UI::DynaFrame::Host.new(...)
|
22
|
+
|
13
23
|
def DynaFrameContent(...) = render Plutonium::UI::DynaFrame::Content.new(...)
|
14
24
|
|
15
25
|
def PageHeader(...) = render Plutonium::UI::PageHeader.new(...)
|
@@ -21,19 +21,37 @@ module Plutonium
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def render_fields
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
24
|
+
Block do
|
25
|
+
fields_wrapper do
|
26
|
+
resource_fields.each do |name|
|
27
|
+
render_resource_field name
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
29
31
|
end
|
30
32
|
|
31
33
|
def render_associations
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
34
|
+
resource_associations.each do |name|
|
35
|
+
reflection = object.class.reflect_on_association name
|
36
|
+
|
37
|
+
if !reflection
|
38
|
+
raise ArgumentError,
|
39
|
+
"unknown association #{object.class}##{name} defined in #permitted_associations"
|
40
|
+
elsif !registered_resources.include?(reflection.klass)
|
41
|
+
raise ArgumentError,
|
42
|
+
"#{object.class}##{name} defined in #permitted_associations, but #{reflection.klass} is not a registered resource"
|
43
|
+
end
|
44
|
+
|
45
|
+
title = object.class.human_attribute_name(name)
|
46
|
+
src = case reflection.macro
|
47
|
+
when :belongs_to
|
48
|
+
associated = object.public_send name
|
49
|
+
resource_url_for(associated, parent: nil) if associated
|
50
|
+
when :has_many
|
51
|
+
resource_url_for(reflection.klass, parent: object)
|
52
|
+
end
|
53
|
+
FrameNavigatorPanel(title:, src:) if src
|
54
|
+
end
|
37
55
|
end
|
38
56
|
|
39
57
|
def render_resource_field(name)
|
@@ -73,7 +91,7 @@ module Plutonium
|
|
73
91
|
end
|
74
92
|
|
75
93
|
def present_associations?
|
76
|
-
|
94
|
+
current_turbo_frame.nil?
|
77
95
|
end
|
78
96
|
end
|
79
97
|
end
|
@@ -6,7 +6,7 @@ module Plutonium
|
|
6
6
|
class Theme < Phlexi::Display::Theme
|
7
7
|
def self.theme
|
8
8
|
super.merge({
|
9
|
-
base: "
|
9
|
+
base: "",
|
10
10
|
value_wrapper: "max-h-[300px] overflow-y-auto",
|
11
11
|
fields_wrapper: "p-6 grid grid-cols-1 md:grid-cols-2 2xl:grid-cols-4 gap-6 gap-y-10 grid-flow-row-dense",
|
12
12
|
label: "text-base font-bold text-gray-500 dark:text-gray-400 mb-1",
|
@@ -0,0 +1,20 @@
|
|
1
|
+
module Plutonium
|
2
|
+
module UI
|
3
|
+
module DynaFrame
|
4
|
+
class Host < Plutonium::UI::Component::Base
|
5
|
+
include Phlex::Rails::Helpers::TurboFrameTag
|
6
|
+
|
7
|
+
def initialize(src:, loading:, id: SecureRandom.hex, **attributes)
|
8
|
+
@id = id
|
9
|
+
@src = src
|
10
|
+
@loading = loading
|
11
|
+
@attributes = attributes
|
12
|
+
end
|
13
|
+
|
14
|
+
def view_template(&)
|
15
|
+
turbo_frame_tag(@id, src: @src, loading: @loading, **@attributes, &)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|