plutonium 0.15.6 → 0.15.8
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/core/assets/templates/tailwind.config.js +11 -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/extra/colorized_logger/colorized_logger_generator.rb +21 -0
- data/lib/generators/pu/extra/colorized_logger/templates/config/initializers/colorized_logger.rb +22 -0
- 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/core/controllers/authorizable.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 +13 -9
- data/lib/plutonium/resource/controllers/authorizable.rb +2 -2
- data/lib/plutonium/resource/controllers/interactive_actions.rb +1 -1
- data/lib/plutonium/resource/controllers/presentable.rb +15 -8
- 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 +285 -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/package-lock.json +2 -2
- data/package.json +1 -1
- data/src/js/controllers/frame_navigator_controller.js +25 -8
- data/src/js/controllers/nested_resource_form_fields_controller.js +2 -2
- data/tailwind.config.js +11 -1
- data/tailwind.options.js +7 -1
- metadata +13 -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' )
|
@@ -1,12 +1,22 @@
|
|
1
1
|
const { execSync } = require('child_process');
|
2
2
|
const plutoniumGemPath = execSync("bundle show plutonium").toString().trim();
|
3
3
|
const plutoniumTailwindConfig = require(`${plutoniumGemPath}/tailwind.options.js`)
|
4
|
+
const tailwindPlugin = require('tailwindcss/plugin')
|
4
5
|
|
5
6
|
module.exports = {
|
6
7
|
darkMode: plutoniumTailwindConfig.darkMode,
|
7
8
|
plugins: [
|
8
9
|
// add plugins here
|
9
|
-
].concat(plutoniumTailwindConfig.plugins.map((plugin)
|
10
|
+
].concat(plutoniumTailwindConfig.plugins.map(function (plugin) {
|
11
|
+
switch (typeof plugin) {
|
12
|
+
case "function":
|
13
|
+
return tailwindPlugin(plugin)
|
14
|
+
case "string":
|
15
|
+
return require(plugin)
|
16
|
+
default:
|
17
|
+
throw Error(`unsupported plugin: ${plugin}: ${(typeof plugin)}`)
|
18
|
+
}
|
19
|
+
})),
|
10
20
|
theme: plutoniumTailwindConfig.theme,
|
11
21
|
content: [
|
12
22
|
`${__dirname}/app/**/*.rb`,
|
@@ -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)
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative "../../lib/plutonium_generators"
|
4
|
+
|
5
|
+
module Pu
|
6
|
+
module Extra
|
7
|
+
class ColorizedLoggerGenerator < Rails::Generators::Base
|
8
|
+
include PlutoniumGenerators::Generator
|
9
|
+
|
10
|
+
source_root File.expand_path("templates", __dir__)
|
11
|
+
|
12
|
+
desc "Set up a colorized logger"
|
13
|
+
|
14
|
+
def start
|
15
|
+
copy_file "config/initializers/colorized_logger.rb"
|
16
|
+
rescue => e
|
17
|
+
exception "#{self.class} failed:", e
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
data/lib/generators/pu/extra/colorized_logger/templates/config/initializers/colorized_logger.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
return unless Rails.env.development?
|
4
|
+
|
5
|
+
# Taken from https://gist.github.com/kyrylo/3d90f7a656d1a0accf244b8f1d25999b?permalink_comment_id=5264120#gistcomment-5264120
|
6
|
+
|
7
|
+
module ColorizedLogger
|
8
|
+
%i[debug info warn error fatal unknown].each do |level|
|
9
|
+
color = case level
|
10
|
+
when :debug then "\e[0;36m" # Cyan text
|
11
|
+
when :info then "\e[0;32m" # Green text
|
12
|
+
when :warn then "\e[1;33m" # Yellow text
|
13
|
+
when :error, :fatal then "\e[1;31m" # Red text
|
14
|
+
else "\e[0m" # Terminal default
|
15
|
+
end
|
16
|
+
|
17
|
+
define_method(level) do |progname = nil, &block|
|
18
|
+
super(color + (progname || (block && block.call)).to_s + "\e[0m")
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
Rails.logger.extend(ColorizedLogger)
|
@@ -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
|
@@ -34,7 +34,7 @@ module Plutonium
|
|
34
34
|
# Gets the resource class for the controller
|
35
35
|
# @return [ActiveRecord::Base] The resource class
|
36
36
|
def resource_class
|
37
|
-
return @resource_class if @resource_class
|
37
|
+
return @resource_class if @resource_class
|
38
38
|
|
39
39
|
name.to_s.gsub(/^#{current_package}::/, "").gsub(/Controller$/, "").classify.constantize
|
40
40
|
rescue NameError
|
@@ -52,14 +52,14 @@ module Plutonium
|
|
52
52
|
# Returns the resource record based on path parameters
|
53
53
|
# @return [ActiveRecord::Base, nil] The resource record
|
54
54
|
def resource_record
|
55
|
-
@resource_record ||= current_authorized_scope.from_path_param(params[:id]).first! if params[:id]
|
55
|
+
@resource_record ||= current_authorized_scope.from_path_param(params[:id]).first! if params[:id]
|
56
56
|
@resource_record
|
57
57
|
end
|
58
58
|
|
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
|
@@ -125,19 +125,23 @@ module Plutonium
|
|
125
125
|
# Applies submitted resource params if they have been passed
|
126
126
|
def maybe_apply_submitted_resource_params!
|
127
127
|
ensure_get_request
|
128
|
-
resource_record.attributes = submitted_resource_params if params[resource_param_key]
|
128
|
+
resource_record.attributes = submitted_resource_params if params[resource_param_key]
|
129
129
|
end
|
130
130
|
|
131
131
|
# Returns the current parent based on path parameters
|
132
132
|
# @return [ActiveRecord::Base, nil] The current parent
|
133
133
|
def current_parent
|
134
|
-
return unless parent_route_param
|
134
|
+
return unless parent_route_param
|
135
135
|
|
136
136
|
@current_parent ||= begin
|
137
137
|
parent_route_key = parent_route_param.to_s.gsub(/_id$/, "").to_sym
|
138
138
|
parent_class = current_engine.resource_register.route_key_lookup[parent_route_key]
|
139
|
-
parent_scope =
|
140
|
-
|
139
|
+
parent_scope = if scoped_to_entity?
|
140
|
+
parent_class.associated_with(current_scoped_entity)
|
141
|
+
else
|
142
|
+
parent_class.all
|
143
|
+
end
|
144
|
+
parent_scope = parent_scope.from_path_param(params[parent_route_param])
|
141
145
|
current_parent = parent_scope.first!
|
142
146
|
authorize! current_parent, to: :read?
|
143
147
|
current_parent
|
@@ -153,7 +157,7 @@ module Plutonium
|
|
153
157
|
# Returns the parent input parameter
|
154
158
|
# @return [Symbol, nil] The parent input parameter
|
155
159
|
def parent_input_param
|
156
|
-
return unless current_parent
|
160
|
+
return unless current_parent
|
157
161
|
|
158
162
|
resource_class.reflect_on_all_associations(:belongs_to).find { |assoc| assoc.klass.name == current_parent.class.name }&.name&.to_sym
|
159
163
|
end
|
@@ -182,7 +186,7 @@ module Plutonium
|
|
182
186
|
# Overrides parent parameters
|
183
187
|
# @param [Hash] input_params The input parameters
|
184
188
|
def override_parent_params(input_params)
|
185
|
-
if current_parent
|
189
|
+
if current_parent
|
186
190
|
if input_params.key?(parent_input_param) || resource_class.method_defined?(:"#{parent_input_param}=")
|
187
191
|
input_params[parent_input_param] = current_parent
|
188
192
|
end
|
@@ -112,7 +112,7 @@ module Plutonium
|
|
112
112
|
#
|
113
113
|
# @return [Hash] default context for the current resource's policy
|
114
114
|
def current_policy_context
|
115
|
-
{
|
115
|
+
{entity_scope: current_parent || entity_scope_for_authorize}
|
116
116
|
end
|
117
117
|
|
118
118
|
# Authorizes the current action for the given record of the current resource
|
@@ -130,7 +130,7 @@ module Plutonium
|
|
130
130
|
#
|
131
131
|
# @return [Array<Symbol>] the list of permitted attributes for the current action
|
132
132
|
def permitted_attributes
|
133
|
-
@permitted_attributes ||= current_policy.send_with_report(:"permitted_attributes_for_#{action_name}")
|
133
|
+
@permitted_attributes ||= current_policy.send_with_report(:"permitted_attributes_for_#{action_name}").freeze
|
134
134
|
end
|
135
135
|
|
136
136
|
# Returns the list of permitted associations for the current resource
|
@@ -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,6 @@ module Plutonium
|
|
5
5
|
extend ActiveSupport::Concern
|
6
6
|
|
7
7
|
included do
|
8
|
-
helper_method :presentable_attributes, :present_associations?
|
9
8
|
helper_method :build_form, :build_detail, :build_collection
|
10
9
|
end
|
11
10
|
|
@@ -14,12 +13,24 @@ module Plutonium
|
|
14
13
|
def presentable_attributes
|
15
14
|
@presentable_attributes ||= begin
|
16
15
|
presentable_attributes = permitted_attributes
|
17
|
-
|
18
|
-
|
16
|
+
if current_parent
|
17
|
+
presentable_attributes -= [parent_input_param, :"#{parent_input_param}_id"]
|
18
|
+
elsif scoped_to_entity?
|
19
|
+
presentable_attributes -= [scoped_entity_param_key, :"#{scoped_entity_param_key}_id"]
|
20
|
+
end
|
19
21
|
presentable_attributes
|
20
22
|
end
|
21
23
|
end
|
22
24
|
|
25
|
+
def submittable_attributes
|
26
|
+
@submittable_attributes ||= begin
|
27
|
+
submittable_attributes = permitted_attributes
|
28
|
+
submittable_attributes -= [parent_input_param, :"#{parent_input_param}_id"] if current_parent
|
29
|
+
submittable_attributes -= [scoped_entity_param_key, :"#{scoped_entity_param_key}_id"] if scoped_to_entity?
|
30
|
+
submittable_attributes
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
23
34
|
def build_collection
|
24
35
|
current_definition.collection_class.new(@resource_records, resource_fields: presentable_attributes, resource_definition: current_definition)
|
25
36
|
end
|
@@ -29,11 +40,7 @@ module Plutonium
|
|
29
40
|
end
|
30
41
|
|
31
42
|
def build_form(record = resource_record)
|
32
|
-
current_definition.form_class.new(record, resource_fields:
|
33
|
-
end
|
34
|
-
|
35
|
-
def present_associations?
|
36
|
-
current_parent.nil?
|
43
|
+
current_definition.form_class.new(record, resource_fields: submittable_attributes, resource_definition: current_definition)
|
37
44
|
end
|
38
45
|
end
|
39
46
|
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, class: 'dyna', &)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|