plutonium 0.10.3 → 0.11.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Rakefile +1 -2
- data/app/assets/application.js.bk +31419 -0
- data/app/assets/plutonium-logo-original.png +0 -0
- data/app/assets/plutonium-logo-white.png +0 -0
- data/app/assets/plutonium-logo.png +0 -0
- data/app/assets/plutonium.css +1 -0
- data/app/assets/plutonium.ico +0 -0
- data/app/assets/plutonium.js +12416 -0
- data/app/assets/plutonium.js.map +7 -0
- data/app/assets/plutonium.min.js +39 -0
- data/app/assets/plutonium.min.js.map +7 -0
- data/app/views/application/_flash_alerts.html.erb +2 -2
- data/app/views/application/_resource_header.html.erb +263 -697
- data/app/views/application/_resource_sidebar.html.erb +14 -12
- data/app/views/components/action_button/action_button_component.rb +3 -3
- data/app/views/components/attributes.rb +184 -0
- data/app/views/components/base.rb +19 -40
- data/app/views/components/block/block_component.html.erb +1 -1
- data/app/views/components/block/block_component.rb +11 -7
- data/app/views/components/breadcrumbs/breadcrumbs_component.rb +3 -3
- data/app/views/components/button/button_component.html.erb +2 -2
- data/app/views/components/button/button_component.rb +10 -5
- data/app/views/components/dyna_frame_content/dyna_frame_content_component.html.erb +1 -0
- data/app/views/components/dyna_frame_content/dyna_frame_content_component.rb +3 -3
- data/app/views/components/dyna_frame_host/dyna_frame_host_component.html.erb +1 -2
- data/app/views/components/dyna_frame_host/dyna_frame_host_component.rb +12 -5
- data/app/views/components/empty_card/empty_card_component.rb +3 -3
- data/app/views/components/form/form_builder.rb +1 -1
- data/app/views/components/form/form_component.rb +3 -3
- data/app/views/components/has_many_panel/has_many_panel_component.html.erb +25 -0
- data/app/views/components/has_many_panel/has_many_panel_component.rb +16 -0
- data/app/views/components/header/header_component.rb +3 -3
- data/app/views/components/interactive_action_form/interactive_action_form_component.rb +3 -3
- data/app/views/components/nav_grid_menu/nav_grid_menu_component.html.erb +24 -0
- data/app/views/components/nav_grid_menu/nav_grid_menu_component.rb +23 -0
- data/app/views/components/nav_grid_menu_item/nav_grid_menu_item_component.html.erb +4 -0
- data/app/views/components/nav_grid_menu_item/nav_grid_menu_item_component.rb +20 -0
- data/app/views/components/nav_user/nav_user_component.html.erb +50 -0
- data/app/views/components/nav_user/nav_user_component.rb +32 -0
- data/app/views/components/nav_user_link/nav_user_link_component.html.erb +7 -0
- data/app/views/components/nav_user_link/nav_user_link_component.rb +23 -0
- data/app/views/components/nav_user_section/nav_user_section_component.html.erb +7 -0
- data/app/views/components/nav_user_section/nav_user_section_component.rb +18 -0
- data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_component.html.erb +1 -3
- data/app/views/components/nested_resource_form_fields/nested_resource_form_fields_component.rb +11 -5
- data/app/views/components/pagination/pagination_component.html.erb +1 -1
- data/app/views/components/pagination/pagination_component.rb +10 -7
- data/app/views/components/panel/panel_component.html.erb +13 -6
- data/app/views/components/panel/panel_component.rb +11 -5
- data/app/views/components/resource_header/resource_header_component.html.erb +81 -0
- data/app/views/components/resource_header/resource_header_component.rb +20 -0
- data/app/views/components/resource_layout/resource_layout_component.html.erb +32 -0
- data/app/views/components/resource_layout/resource_layout_component.rb +39 -0
- data/app/views/components/sidebar/sidebar_component.html.erb +3 -33
- data/app/views/components/sidebar/sidebar_component.rb +3 -3
- data/app/views/components/sidebar_menu/sidebar_menu_component.html.erb +4 -2
- data/app/views/components/sidebar_menu/sidebar_menu_component.rb +10 -6
- data/app/views/components/sidebar_menu_item/sidebar_menu_item_component.html.erb +63 -71
- data/app/views/components/sidebar_menu_item/sidebar_menu_item_component.rb +27 -8
- data/app/views/components/skeleton/table/table_component.html.erb +1 -1
- data/app/views/components/skeleton/table/table_component.rb +3 -3
- data/app/views/components/table/table_component.html.erb +40 -89
- data/app/views/components/table/table_component.rb +124 -28
- data/app/views/components/table_search_input/table_search_input_component.html.erb +1 -1
- data/app/views/components/table_search_input/table_search_input_component.rb +11 -6
- data/app/views/components/table_toolbar/table_toolbar_component.html.erb +1 -1
- data/app/views/components/table_toolbar/table_toolbar_component.rb +11 -3
- data/app/views/components/toolbar/toolbar_component.html.erb +2 -2
- data/app/views/components/toolbar/toolbar_component.rb +16 -8
- data/app/views/layouts/resource.html.erb +21 -37
- data/app/views/layouts/rodauth.html.erb +32 -30
- data/app/views/resource/_interactive_resource_action_form.html.erb +1 -1
- data/app/views/resource/_resource_details.html.erb +8 -5
- data/app/views/resource/_resource_table.html.erb +70 -1
- data/app/views/resource/interactive_resource_collection_action.html.erb +1 -0
- data/app/views/resource/interactive_resource_record_action.html.erb +1 -0
- data/app/views/resource/interactive_resource_recordless_action.html.erb +1 -0
- data/app/views/resource/new.html.erb +1 -0
- data/config/initializers/simple_form.rb +22 -2
- data/esbuild.config.js +35 -31
- data/lib/generators/pu/core/assets/assets_generator.rb +41 -0
- data/lib/generators/pu/core/assets/templates/tailwind.config.js +18 -0
- data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +3 -0
- data/lib/generators/pu/gem/dotenv/templates/config/initializers/001_ensure_required_env.rb +6 -0
- data/lib/generators/pu/gen/component/component_generator.rb +13 -10
- data/lib/generators/pu/gen/component/templates/component.html.erb.tt +1 -1
- data/lib/generators/pu/gen/component/templates/component.rb.tt +10 -4
- data/lib/generators/pu/pkg/app/app_generator.rb +4 -4
- data/lib/generators/pu/pkg/app/templates/app/controllers/concerns/controller.rb.tt +28 -0
- data/lib/generators/pu/pkg/app/templates/app/controllers/controller.rb.tt +5 -0
- data/lib/generators/pu/pkg/app/templates/app/controllers/dashboard_controller.rb.tt +1 -1
- data/lib/generators/pu/res/conn/conn_generator.rb +4 -4
- data/lib/generators/pu/res/conn/templates/app/controllers/resource_controller.rb.tt +1 -1
- data/lib/generators/pu/res/model/model_generator.rb +3 -3
- data/lib/generators/pu/res/scaffold/templates/policy.rb.tt +6 -0
- data/lib/generators/pu/service/sidekiq/sidekiq_generator.rb +0 -5
- data/lib/generators/pu/service/sidekiq/templates/app/sidekiq/sidekiq_job.rb +0 -2
- data/lib/plutonium/config.rb +2 -14
- data/lib/plutonium/core/associations/renderers/basic_renderer.rb +28 -0
- data/lib/plutonium/core/associations/renderers/factory.rb +36 -0
- data/lib/plutonium/core/associations/renderers/has_many_renderer.rb +16 -0
- data/lib/plutonium/core/autodiscovery/association_renderer_discoverer.rb +31 -0
- data/lib/plutonium/core/controllers/authorizable.rb +13 -17
- data/lib/plutonium/core/controllers/base.rb +3 -7
- data/lib/plutonium/core/controllers/presentable.rb +6 -1
- data/lib/plutonium/core/definers/association_renderer_definer.rb +33 -0
- data/lib/plutonium/core/fields/inputs/checkbox_input.rb +13 -0
- data/lib/plutonium/core/fields/inputs/factory.rb +1 -0
- data/lib/plutonium/core/fields/inputs/polymorphic_belongs_to_association_input.rb +1 -1
- data/lib/plutonium/core/ui/detail.rb +1 -0
- data/lib/plutonium/helpers/application_helper.rb +8 -9
- data/lib/plutonium/helpers/assets_helper.rb +33 -0
- data/lib/plutonium/helpers/display_helper.rb +13 -0
- data/lib/plutonium/helpers/form_helper.rb +1 -1
- data/lib/plutonium/helpers.rb +1 -0
- data/lib/plutonium/icons.rb +12 -5
- data/lib/plutonium/pkg/app.rb +10 -0
- data/lib/plutonium/pundit/context.rb +18 -0
- data/lib/plutonium/pundit/policy_finder.rb +25 -0
- data/lib/plutonium/railtie.rb +20 -8
- data/lib/plutonium/reloader.rb +18 -7
- data/lib/plutonium/resource/controller.rb +4 -0
- data/lib/plutonium/resource/policy.rb +69 -47
- data/lib/plutonium/resource/presenter.rb +1 -0
- data/lib/plutonium/resource/query_object.rb +139 -130
- data/lib/plutonium/rodauth/controller_methods.rb +7 -3
- data/lib/plutonium/version.rb +1 -1
- data/lib/plutonium.rb +9 -57
- data/package-lock.json +782 -17
- data/package.json +31 -8
- data/postcss.config.js +17 -7
- data/src/.npmignore +2 -0
- data/src/js/controllers/color_mode_controller.js +41 -0
- data/src/js/controllers/frame_navigator_controller.js +99 -0
- data/src/js/controllers/has_many_panel_controller.js +8 -0
- data/src/js/controllers/nav_grid_menu_controller.js +8 -0
- data/src/js/controllers/nav_grid_menu_item_controller.js +8 -0
- data/{app/views/components/tab_bar/tab_bar_controller.js → src/js/controllers/nav_user_controller.js} +2 -2
- data/src/js/controllers/nav_user_link_controller.js +8 -0
- data/src/js/controllers/nav_user_section_controller.js +8 -0
- data/src/js/controllers/register_controllers.js +45 -0
- data/{app/assets/javascripts → src/js}/controllers/resource_dismiss_controller.js +2 -0
- data/{app/assets/javascripts → src/js}/controllers/resource_drop_down_controller.js +2 -0
- data/src/js/controllers/resource_header_controller.js +8 -0
- data/src/js/controllers/resource_layout_controller.js +8 -0
- data/src/js/controllers/sidebar_menu_controller.js +8 -0
- data/src/js/controllers/sidebar_menu_item_controller.js +8 -0
- data/src/js/core.js +4 -0
- data/{app/assets/javascripts/plutonium-app.js → src/js/plutonium.js} +1 -1
- data/{app/assets/javascripts → src/js}/turbo/turbo_debug.js +2 -4
- data/tailwind.config.js +85 -84
- metadata +73 -39
- data/app/assets/build/plutonium.js +0 -5122
- data/app/assets/javascripts/controllers/index.js +0 -34
- data/app/assets/javascripts/plutonium.js +0 -1
- data/app/views/application/_color_modes.html.erb +0 -57
- data/app/views/components/tab_bar/tab_bar_component.html.erb +0 -11
- data/app/views/components/tab_bar/tab_bar_component.rb +0 -9
- data/app/views/resource/_nav_user.html.erb +0 -4
- data/app/views/resource/_tab_menu.html.erb +0 -13
- data/css.manifest +0 -3
- data/js.manifest +0 -4
- data/lib/generators/pu/pkg/app/templates/app/controllers/app_controller.rb.tt +0 -5
- data/lib/generators/pu/pkg/app/templates/app/controllers/package_controller.rb.tt +0 -26
- data/public/plutonium-assets/application.css +0 -25086
- data/public/plutonium-assets/plutonium-app-36KN5FVJ.js +0 -6
- data/public/plutonium-assets/plutonium-app-36KN5FVJ.js.map +0 -7
- data/public/plutonium-assets/plutonium-app-6WILQCTT.js +0 -39
- data/public/plutonium-assets/plutonium-app-6WILQCTT.js.map +0 -7
- data/public/plutonium-assets/plutonium.2d4f0c333cd000051d3b.css +0 -3424
- data/public/plutonium-assets/plutonium.50232e35b5495f5ad90d.css +0 -3415
- data/public/plutonium-assets/plutonium.8bee7a8482988b0360e3.css +0 -3420
- /data/{app/assets/build → lib/generators/pu/core/assets/templates}/.keep +0 -0
- /data/{app/assets/stylesheets → src/css}/plutonium.css +0 -0
- /data/{app/views/components/form → src/js/controllers}/form_controller.js +0 -0
- /data/{app/views/components/interactive_action_form → src/js/controllers}/interactive_action_form_controller.js +0 -0
- /data/{app/views/components/nested_resource_form_fields → src/js/controllers}/nested_resource_form_fields_controller.js +0 -0
- /data/{app/views/components/table → src/js/controllers}/table_controller.js +0 -0
- /data/{app/views/components/table_search_input → src/js/controllers}/table_search_input_controller.js +0 -0
- /data/{app/views/components/table_toolbar → src/js/controllers}/table_toolbar_controller.js +0 -0
- /data/{app/views/components/toolbar → src/js/controllers}/toolbar_controller.js +0 -0
- /data/{app/assets/javascripts → src/js}/turbo/index.js +0 -0
- /data/{app/assets/javascripts → src/js}/turbo/turbo_actions.js +0 -0
- /data/{app/assets/javascripts → src/js}/turbo/turbo_frame_monkey_patch.js +0 -0
@@ -1,72 +1,64 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
<
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
1
|
+
<li <%= attributes_html %>>
|
2
|
+
<% if sub_items.any? %>
|
3
|
+
<button
|
4
|
+
type="button"
|
5
|
+
class="<%= link_button_class %> w-full transition duration-75"
|
6
|
+
data-resource-drop-down-target="trigger"
|
7
|
+
aria-controls="dropdown-<%= name.parameterize %>">
|
8
|
+
<% if icon.present? %>
|
9
|
+
<%= render_icon icon, size: :lg %>
|
10
|
+
<% else %>
|
11
|
+
<div class="shrink-0 w-6 h-6">
|
12
|
+
|
13
|
+
</div>
|
14
|
+
<% end %>
|
15
|
+
<span class="<%= link_label_class %>"><%= name %></span>
|
16
|
+
<svg
|
17
|
+
aria-hidden="true"
|
18
|
+
class="w-6 h-6"
|
19
|
+
fill="currentColor"
|
20
|
+
viewBox="0 0 20 20"
|
21
|
+
xmlns="http://www.w3.org/2000/svg"
|
22
|
+
>
|
23
|
+
<path
|
24
|
+
fill-rule="evenodd"
|
25
|
+
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
26
|
+
clip-rule="evenodd"
|
27
|
+
></path>
|
28
|
+
</svg>
|
29
|
+
</button>
|
30
|
+
|
31
|
+
<ul id="dropdown-<%= name.parameterize %>" data-resource-drop-down-target="menu" class="hidden py-2 space-y-2">
|
32
|
+
<% sub_items.each do |sub_item| %>
|
33
|
+
<%#= sub_item %>
|
34
|
+
<li>
|
35
|
+
<a
|
36
|
+
href="<%= sub_item.url %>"
|
37
|
+
class="<%= sub_link_button_class %>">
|
38
|
+
<%= sub_item.name %>
|
39
|
+
</a>
|
40
|
+
</li>
|
41
|
+
<% end %>
|
42
|
+
</ul>
|
43
|
+
<% else %>
|
44
|
+
<a
|
45
|
+
href="<%= url %>"
|
46
|
+
class="<%= link_button_class %>">
|
47
|
+
<% if icon.present? %>
|
48
|
+
<%= render_icon icon, size: :lg %>
|
49
|
+
<% else %>
|
50
|
+
<div class="shrink-0 w-6 h-6">
|
51
|
+
|
52
|
+
</div>
|
53
|
+
<% end %>
|
54
|
+
<span class="<%= link_label_class %>"><%= name %></span>
|
55
|
+
<%#
|
56
|
+
<% if indicator.present? % >
|
57
|
+
<span class="inline-flex justify-center items-center w-5 h-5 text-xs font-semibold rounded-full text-primary-800 bg-primary-100 dark:bg-primary-200 dark:text-primary-800">
|
58
|
+
<%= indicator % >
|
59
|
+
</span>
|
60
|
+
<% end % >
|
61
|
+
%>
|
62
|
+
</a>
|
63
|
+
<% end %>
|
24
64
|
</li>
|
25
|
-
<% else %>
|
26
|
-
<li>
|
27
|
-
<button
|
28
|
-
type="button"
|
29
|
-
class="<%= link_button_class %> w-full transition duration-75"
|
30
|
-
aria-controls="dropdown-<%= name.parameterize %>"
|
31
|
-
data-collapse-toggle="dropdown-<%= name.parameterize %>"
|
32
|
-
>
|
33
|
-
<svg
|
34
|
-
aria-hidden="true"
|
35
|
-
class="shrink-0 w-6 h-6 text-gray-500 transition duration-75 group-hover:text-gray-900 dark:text-gray-200 dark:group-hover:text-white"
|
36
|
-
fill="currentColor"
|
37
|
-
viewBox="0 0 20 20"
|
38
|
-
xmlns="http://www.w3.org/2000/svg"
|
39
|
-
>
|
40
|
-
<path
|
41
|
-
fill-rule="evenodd"
|
42
|
-
d="M10 2a4 4 0 00-4 4v1H5a1 1 0 00-.994.89l-1 9A1 1 0 004 18h12a1 1 0 00.994-1.11l-1-9A1 1 0 0015 7h-1V6a4 4 0 00-4-4zm2 5V6a2 2 0 10-4 0v1h4zm-6 3a1 1 0 112 0 1 1 0 01-2 0zm7-1a1 1 0 100 2 1 1 0 000-2z"
|
43
|
-
clip-rule="evenodd"
|
44
|
-
></path>
|
45
|
-
</svg>
|
46
|
-
<span class="<%= link_label_class %>"><%= name %></span>
|
47
|
-
<svg
|
48
|
-
aria-hidden="true"
|
49
|
-
class="w-6 h-6"
|
50
|
-
fill="currentColor"
|
51
|
-
viewBox="0 0 20 20"
|
52
|
-
xmlns="http://www.w3.org/2000/svg"
|
53
|
-
>
|
54
|
-
<path
|
55
|
-
fill-rule="evenodd"
|
56
|
-
d="M5.293 7.293a1 1 0 011.414 0L10 10.586l3.293-3.293a1 1 0 111.414 1.414l-4 4a1 1 0 01-1.414 0l-4-4a1 1 0 010-1.414z"
|
57
|
-
clip-rule="evenodd"
|
58
|
-
></path>
|
59
|
-
</svg>
|
60
|
-
</button>
|
61
|
-
<ul id="dropdown-<%= name.parameterize %>" class="hidden py-2 space-y-2">
|
62
|
-
<% value.each do |name, value| %>
|
63
|
-
<li>
|
64
|
-
<a
|
65
|
-
href="<%= value %>"
|
66
|
-
class="<%= sub_link_button_class %>"
|
67
|
-
><%= name %></a>
|
68
|
-
</li>
|
69
|
-
<% end %>
|
70
|
-
</ul>
|
71
|
-
</li>
|
72
|
-
<% end %>
|
@@ -1,23 +1,42 @@
|
|
1
|
-
module
|
2
|
-
class SidebarMenuItemComponent <
|
1
|
+
module PlutoniumUi
|
2
|
+
class SidebarMenuItemComponent < PlutoniumUi::Base
|
3
|
+
renders_many :sub_items, "::PlutoniumUi::SidebarMenuItemComponent"
|
4
|
+
|
3
5
|
option :name
|
4
|
-
option :
|
5
|
-
option :
|
6
|
+
option :url, default: -> { "" }
|
7
|
+
option :options, default: -> { {} }
|
8
|
+
option :icon, optional: true
|
6
9
|
|
7
10
|
private
|
8
11
|
|
12
|
+
def base_attributes
|
13
|
+
# base attributes go here
|
14
|
+
{
|
15
|
+
id: "sidebar-menu-item-#{name.parameterize}",
|
16
|
+
classname: "sidebar-menu-item",
|
17
|
+
controller: ["sidebar-menu-item", sub_items.any? ? "resource-drop-down" : nil],
|
18
|
+
link_button_class: "group flex items-center rounded-lg p-2 text-base font-medium text-gray-900 hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700",
|
19
|
+
link_label_class: "flex-1 ml-3 text-left whitespace-nowrap",
|
20
|
+
sub_link_button_class: "flex items-center p-2 pl-11 w-full text-base font-medium text-gray-900 rounded-lg transition duration-75 group hover:bg-gray-100 dark:text-white dark:hover:bg-gray-700"
|
21
|
+
}
|
22
|
+
end
|
23
|
+
|
24
|
+
def filtered_attributes
|
25
|
+
%i[link_button_class link_label_class sub_link_button_class]
|
26
|
+
end
|
27
|
+
|
9
28
|
def link_button_class
|
10
|
-
|
29
|
+
raw_attributes_hash[:link_button_class]
|
11
30
|
end
|
12
31
|
|
13
32
|
def link_label_class
|
14
|
-
|
33
|
+
raw_attributes_hash[:link_label_class]
|
15
34
|
end
|
16
35
|
|
17
36
|
def sub_link_button_class
|
18
|
-
|
37
|
+
raw_attributes_hash[:sub_link_button_class]
|
19
38
|
end
|
20
39
|
end
|
21
40
|
end
|
22
41
|
|
23
|
-
Plutonium::ComponentRegistry.register :sidebar_menu_item, to:
|
42
|
+
Plutonium::ComponentRegistry.register :sidebar_menu_item, to: PlutoniumUi::SidebarMenuItemComponent
|
@@ -1,5 +1,5 @@
|
|
1
1
|
|
2
|
-
<div role="status" class="p-4 space-y-4 border border-gray-200 divide-y divide-gray-200 rounded shadow animate-pulse dark:divide-gray-700 md:p-6 dark:border-gray-700">
|
2
|
+
<div role="status" class="p-4 space-y-4 border border-gray-200 divide-y divide-gray-200 rounded shadow motion-safe:animate-pulse dark:divide-gray-700 md:p-6 dark:border-gray-700">
|
3
3
|
<div class="flex items-center justify-between">
|
4
4
|
<div>
|
5
5
|
<div class="h-2.5 bg-gray-300 rounded-full dark:bg-gray-600 w-24 mb-2.5"></div>
|
@@ -1,6 +1,6 @@
|
|
1
|
-
module
|
2
|
-
class TableComponent <
|
1
|
+
module PlutoniumUi::Skeleton
|
2
|
+
class TableComponent < PlutoniumUi::Base
|
3
3
|
end
|
4
4
|
end
|
5
5
|
|
6
|
-
Plutonium::ComponentRegistry.register :skeleton__table, to:
|
6
|
+
Plutonium::ComponentRegistry.register :skeleton__table, to: PlutoniumUi::Skeleton::TableComponent
|
@@ -1,92 +1,43 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
1
|
+
<table <%= attributes_html %>>
|
2
|
+
<thead class="<%= table_head_classname %>">
|
3
|
+
<tr>
|
4
|
+
<th scope="col" class="p-4">
|
5
|
+
<div class="flex items-center">
|
6
|
+
<input id="checkbox-all-search" type="checkbox" class="w-4 h-4 text-primary-600 bg-gray-100 border-gray-300 rounded focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
7
|
+
<label for="checkbox-all-search" class="sr-only">checkbox</label>
|
8
|
+
</div>
|
9
|
+
</th>
|
10
|
+
<% @columns.each do |column| %>
|
11
|
+
<th scope="col" class="<%= table_head_cell_classname %>">
|
12
|
+
<%= table_head_cell column %>
|
13
|
+
</th>
|
14
|
+
<% end %>
|
15
|
+
<% if actions_block.present? %>
|
16
|
+
<th scope="col" class="<%= table_actions_head_classname %>"> </th>
|
17
|
+
<% end %>
|
18
|
+
</tr>
|
19
|
+
</thead>
|
20
|
+
<tbody>
|
21
|
+
<% @rows.each do |row| %>
|
22
|
+
<tr class="<%= table_row_classname %>">
|
23
|
+
<th scope="row" class="w-4 p-4">
|
24
|
+
<div class="flex items-center">
|
25
|
+
<input id="checkbox-table-search-1" type="checkbox" class="w-4 h-4 text-primary-600 bg-gray-100 border-gray-300 rounded focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
26
|
+
<label for="checkbox-table-search-1" class="sr-only">checkbox</label>
|
27
|
+
</div>
|
28
|
+
</th>
|
29
|
+
<% @columns.each do |column| %>
|
30
|
+
<td class="<%= table_row_cell_classname %>">
|
31
|
+
<%# the capture ensures, that we do not only return the return of the block, but all the html from the block %>
|
32
|
+
<%= view_context.capture(row, &column.td_block) %>
|
33
|
+
</td>
|
24
34
|
<% end %>
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
<%= render_component :block, id: "resource-table-container", scroll: :x, rounded: table_rounding, data: {controller:"scroll-preserver", action: "scroll->scroll-preserver#scrolled"} do %>
|
30
|
-
<% unless resources.any? %>
|
31
|
-
<div class="col-12">
|
32
|
-
<%=
|
33
|
-
render_component :empty_card, message: "No #{resource_name_plural(resource_class).downcase} match your query" do
|
34
|
-
if current_policy.create?
|
35
|
-
render_component :button, label: "Create #{resource_name(resource_class)}",
|
36
|
-
to: resource_url_for(resource_class, action: :new),
|
37
|
-
color: :primary
|
38
|
-
end
|
39
|
-
end
|
40
|
-
%>
|
41
|
-
</div>
|
42
|
-
<% else %>
|
43
|
-
<table data-controller="table" <%= render_component_attributes %>>
|
44
|
-
<thead class="<%= table_head_classes %>">
|
45
|
-
<tr>
|
46
|
-
<th scope="col" class="p-4">
|
47
|
-
<div class="flex items-center">
|
48
|
-
<input id="checkbox-all-search" type="checkbox" class="w-4 h-4 text-primary-600 bg-gray-100 border-gray-300 rounded focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
49
|
-
<label for="checkbox-all-search" class="sr-only">checkbox</label>
|
50
|
-
</div>
|
51
|
-
</th>
|
52
|
-
<% fields.each do |name, field| %>
|
53
|
-
<th scope="col" class="px-6 py-3">
|
54
|
-
<%= table_header name, field.label, search_object %>
|
55
|
-
</th>
|
56
|
-
<% end %>
|
57
|
-
<th scope="col" class="px-6 py-3 text-end"> </th>
|
58
|
-
</tr>
|
59
|
-
</thead>
|
60
|
-
<tbody>
|
61
|
-
<% resources.each do |resource| %>
|
62
|
-
<tr class="<%= table_row_classes %>">
|
63
|
-
<th scope="row" class="w-4 p-4">
|
64
|
-
<div class="flex items-center">
|
65
|
-
<input id="checkbox-table-search-1" type="checkbox" class="w-4 h-4 text-primary-600 bg-gray-100 border-gray-300 rounded focus:ring-primary-500 dark:focus:ring-primary-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
|
66
|
-
<label for="checkbox-table-search-1" class="sr-only">checkbox</label>
|
67
|
-
</div>
|
68
|
-
</th>
|
69
|
-
<% fields.each do |name, field| %>
|
70
|
-
<%
|
71
|
-
options = field.options
|
72
|
-
max_width = options.delete :pu_max_width
|
73
|
-
%>
|
74
|
-
<td class="<%= table_row_cell_classes %>">
|
75
|
-
<%= field.render self, resource %>
|
76
|
-
</td>
|
77
|
-
<% end %>
|
78
|
-
<td class="<%= table_actions_cell_classes %>">
|
79
|
-
<% record_actions.permitted_for(policy(resource)).values.each do |action| %>
|
80
|
-
<%= table_action_button resource, action %>
|
81
|
-
<% end %>
|
82
|
-
</td>
|
83
|
-
</tr>
|
35
|
+
<% if actions_block.present? %>
|
36
|
+
<td class="<%= table_actions_row_classname %>">
|
37
|
+
<%= view_context.capture(row, &actions_block) %>
|
38
|
+
</td>
|
84
39
|
<% end %>
|
85
|
-
</
|
86
|
-
</table>
|
87
|
-
|
88
|
-
<% if pager.present? %>
|
89
|
-
<%= render_component :pagination, pager: pager %>
|
40
|
+
</tr>
|
90
41
|
<% end %>
|
91
|
-
|
92
|
-
|
42
|
+
</tbody>
|
43
|
+
</table>
|
@@ -1,63 +1,159 @@
|
|
1
|
-
module
|
2
|
-
|
3
|
-
|
4
|
-
option :
|
5
|
-
option :record_actions
|
6
|
-
option :search_object
|
7
|
-
option :fields
|
8
|
-
option :pager
|
1
|
+
module PlutoniumUi
|
2
|
+
# TableComponent is a UI component that represents a table with sortable columns and optional row actions.
|
3
|
+
class TableComponent < PlutoniumUi::Base
|
4
|
+
option :rows
|
9
5
|
|
10
|
-
|
11
|
-
|
6
|
+
attr_reader :columns, :actions_block
|
7
|
+
|
8
|
+
# Initializes the TableComponent with the given options.
|
9
|
+
#
|
10
|
+
# @param options [Hash] The options for the component.
|
11
|
+
def initialize(...)
|
12
|
+
super(...)
|
13
|
+
@columns = []
|
14
|
+
end
|
15
|
+
|
16
|
+
# Defines a column in the table.
|
17
|
+
#
|
18
|
+
# @param name [Symbol] The name of the column.
|
19
|
+
# @param label [String] The label of the column.
|
20
|
+
# @param search_object [Object] The search object associated with the column.
|
21
|
+
# @param block [Proc] An optional block for additional column customization.
|
22
|
+
def column(name:, label:, search_object:, &block)
|
23
|
+
@columns ||= []
|
24
|
+
@columns << Column.new(name:, label:, search_object:, &block)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Returns the base attributes for the table.
|
28
|
+
#
|
29
|
+
# @return [Hash] The base attributes hash.
|
30
|
+
def base_attributes
|
31
|
+
{
|
32
|
+
classname: "table-auto w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-200",
|
33
|
+
table_head_classname: "text-xs text-gray-700 uppercase bg-gray-200 dark:bg-gray-700 dark:text-gray-200",
|
34
|
+
table_head_cell_classname: "px-6 py-3",
|
35
|
+
table_row_classname: "bg-white border-b dark:bg-gray-800 dark:border-gray-700 hover:bg-gray-50 dark:hover:bg-gray-600",
|
36
|
+
table_row_cell_classname: "px-6 py-4 whitespace-nowrap max-w-[250px] hover:max-w-fit overflow-hidden text-ellipsis",
|
37
|
+
table_actions_head_classname: "px-6 py-3 text-end",
|
38
|
+
table_actions_row_classname: "flex justify-end px-6 py-4"
|
39
|
+
}
|
40
|
+
end
|
41
|
+
|
42
|
+
def filtered_attributes
|
43
|
+
base_attributes.keys - possible_attributes
|
44
|
+
end
|
45
|
+
|
46
|
+
# Defines a block of actions to be included in each row.
|
47
|
+
#
|
48
|
+
# @param block [Proc] The block defining the actions.
|
49
|
+
def with_actions(&block)
|
50
|
+
@actions_block = block
|
12
51
|
end
|
13
52
|
|
14
53
|
private
|
15
54
|
|
16
|
-
|
17
|
-
|
55
|
+
# Ensures that the view component calls the block, and @columns get populated.
|
56
|
+
def before_render
|
57
|
+
content
|
18
58
|
end
|
19
59
|
|
20
|
-
|
21
|
-
|
60
|
+
# Retrieves the CSS class for the table head.
|
61
|
+
#
|
62
|
+
# @return [String] The CSS class for the table head.
|
63
|
+
def table_head_classname
|
64
|
+
raw_attributes_hash[:table_head_classname]
|
22
65
|
end
|
23
66
|
|
24
|
-
|
25
|
-
|
67
|
+
# Retrieves the CSS class for a table head cell.
|
68
|
+
#
|
69
|
+
# @return [String] The CSS class for a table head cell.
|
70
|
+
def table_head_cell_classname
|
71
|
+
raw_attributes_hash[:table_head_cell_classname]
|
26
72
|
end
|
27
73
|
|
28
|
-
|
29
|
-
|
74
|
+
# Retrieves the CSS class for a table row.
|
75
|
+
#
|
76
|
+
# @return [String] The CSS class for a table row.
|
77
|
+
def table_row_classname
|
78
|
+
raw_attributes_hash[:table_row_classname]
|
30
79
|
end
|
31
80
|
|
32
|
-
|
33
|
-
|
81
|
+
# Retrieves the CSS class for a table row cell.
|
82
|
+
#
|
83
|
+
# @return [String] The CSS class for a table row cell.
|
84
|
+
def table_row_cell_classname
|
85
|
+
raw_attributes_hash[:table_row_cell_classname]
|
34
86
|
end
|
35
87
|
|
36
|
-
|
88
|
+
# Retrieves the CSS class for the table actions head.
|
89
|
+
#
|
90
|
+
# @return [String] The CSS class for the table actions head.
|
91
|
+
def table_actions_head_classname
|
92
|
+
raw_attributes_hash[:table_actions_head_classname]
|
93
|
+
end
|
94
|
+
|
95
|
+
# Retrieves the CSS class for the table actions row.
|
96
|
+
#
|
97
|
+
# @return [String] The CSS class for the table actions row.
|
98
|
+
def table_actions_row_classname
|
99
|
+
raw_attributes_hash[:table_actions_row_classname]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Generates the content for a table head cell, including sorting links if applicable.
|
103
|
+
#
|
104
|
+
# @param column [Column] The column object.
|
105
|
+
# @return [String] The HTML content for the table head cell.
|
106
|
+
def table_head_cell(column)
|
107
|
+
name = column.name
|
108
|
+
label = column.label
|
109
|
+
search_object = column.search_object
|
110
|
+
|
37
111
|
if (sort_params = search_object.sort_params_for(name))
|
38
|
-
tag.
|
112
|
+
tag.div class: "inline-flex" do
|
39
113
|
concat begin
|
40
|
-
link_to(sort_params[:url], class: "
|
114
|
+
link_to(sort_params[:url], class: "flex", title: sort_params[:direction] || "Sort") do
|
41
115
|
concat label
|
42
116
|
if sort_params[:direction].present?
|
43
117
|
icon = (sort_params[:direction] == "ASC") ? "up" : "down"
|
44
118
|
concat " "
|
45
|
-
concat
|
119
|
+
concat render_icon("outline/arrow-#{icon}")
|
46
120
|
end
|
47
121
|
end
|
48
122
|
end
|
123
|
+
|
49
124
|
if sort_params[:position].present?
|
50
125
|
concat " "
|
51
|
-
concat link_to(
|
52
|
-
|
53
|
-
|
126
|
+
concat link_to(
|
127
|
+
sort_params[:position] + 1,
|
128
|
+
sort_params[:reset_url],
|
129
|
+
class: "inline-flex items-center justify-center w-4 h-4 text-xs font-bold text-white bg-yellow-500 border-1 border-white rounded-full dark:border-gray-90",
|
130
|
+
title: "Clear sorting"
|
131
|
+
)
|
54
132
|
end
|
55
133
|
end
|
56
134
|
else
|
57
135
|
label
|
58
136
|
end
|
59
137
|
end
|
138
|
+
|
139
|
+
# A value object to hold the column definition.
|
140
|
+
class Column
|
141
|
+
attr_reader :name, :label, :search_object, :td_block
|
142
|
+
|
143
|
+
# Initializes a Column object with the given attributes.
|
144
|
+
#
|
145
|
+
# @param name [Symbol] The name of the column.
|
146
|
+
# @param label [String] The label of the column.
|
147
|
+
# @param search_object [Object] The search object associated with the column.
|
148
|
+
# @param block [Proc] An optional block for additional column customization.
|
149
|
+
def initialize(name:, label:, search_object:, &block)
|
150
|
+
@name = name
|
151
|
+
@label = label
|
152
|
+
@search_object = search_object
|
153
|
+
@td_block = block
|
154
|
+
end
|
155
|
+
end
|
60
156
|
end
|
61
157
|
end
|
62
158
|
|
63
|
-
Plutonium::ComponentRegistry.register :table, to:
|
159
|
+
Plutonium::ComponentRegistry.register :table, to: PlutoniumUi::TableComponent
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div
|
1
|
+
<div <%= attributes_html %>>
|
2
2
|
<%= simple_form_for :q, url: "", method: :get, html: { class: "flex items-center", data: { controller: "form", turbo_frame: nil } } do |f| %>
|
3
3
|
<label for="search" class="sr-only">Search</label>
|
4
4
|
<div class="relative w-full">
|
@@ -1,10 +1,15 @@
|
|
1
|
-
module
|
2
|
-
class TableSearchInputComponent <
|
1
|
+
module PlutoniumUi
|
2
|
+
class TableSearchInputComponent < PlutoniumUi::Base
|
3
3
|
option :search_object
|
4
|
-
|
5
|
-
|
6
|
-
|
4
|
+
|
5
|
+
private
|
6
|
+
|
7
|
+
def base_attributes
|
8
|
+
{
|
9
|
+
controller: "table-search-input"
|
10
|
+
}
|
11
|
+
end
|
7
12
|
end
|
8
13
|
end
|
9
14
|
|
10
|
-
Plutonium::ComponentRegistry.register :table_search_input, to:
|
15
|
+
Plutonium::ComponentRegistry.register :table_search_input, to: PlutoniumUi::TableSearchInputComponent
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<div
|
1
|
+
<div <%= attributes_html %>>
|
2
2
|
<%= render_component :toolbar, actions:, resource: resource_class do %>
|
3
3
|
<% if search_object.search_filter.present? && current_policy.search? %>
|
4
4
|
<%= render_component "table_search_input", search_object: search_object %>
|
@@ -1,9 +1,17 @@
|
|
1
|
-
module
|
2
|
-
class TableToolbarComponent <
|
1
|
+
module PlutoniumUi
|
2
|
+
class TableToolbarComponent < PlutoniumUi::Base
|
3
3
|
option :resource_class
|
4
4
|
option :search_object
|
5
5
|
option :actions
|
6
|
+
|
7
|
+
private
|
8
|
+
|
9
|
+
def base_attributes
|
10
|
+
{
|
11
|
+
controller: "table-toolbar"
|
12
|
+
}
|
13
|
+
end
|
6
14
|
end
|
7
15
|
end
|
8
16
|
|
9
|
-
Plutonium::ComponentRegistry.register :table_toolbar, to:
|
17
|
+
Plutonium::ComponentRegistry.register :table_toolbar, to: PlutoniumUi::TableToolbarComponent
|
@@ -1,9 +1,9 @@
|
|
1
1
|
<%#= render_component :panel do %>
|
2
|
-
<div
|
2
|
+
<div <%= attributes_html %>>
|
3
3
|
<div class="w-full md:w-1/2">
|
4
4
|
<%= content %>
|
5
5
|
</div>
|
6
|
-
<div class="<%=
|
6
|
+
<div class="<%= toolbar_actions_classname %>">
|
7
7
|
<% actions.values.each do |action| %>
|
8
8
|
<%= toolbar_action_button resource, action %>
|
9
9
|
<% end %>
|
@@ -1,18 +1,26 @@
|
|
1
|
-
module
|
2
|
-
class ToolbarComponent <
|
1
|
+
module PlutoniumUi
|
2
|
+
class ToolbarComponent < PlutoniumUi::Base
|
3
3
|
option :resource
|
4
4
|
option :actions, default: proc { {} }
|
5
5
|
|
6
|
-
|
7
|
-
|
6
|
+
private
|
7
|
+
|
8
|
+
def base_attributes
|
9
|
+
{
|
10
|
+
classname: "flex flex-col md:flex-row items-center justify-between space-y-3 md:space-y-0 md:space-x-4",
|
11
|
+
toolbar_actions_classname: "w-full md:w-auto flex flex-col md:flex-row space-y-1 md:space-y-0 items-stretch md:items-center justify-end shrink-0",
|
12
|
+
controller: "toolbar"
|
13
|
+
}
|
8
14
|
end
|
9
15
|
|
10
|
-
|
16
|
+
def filtered_attributes
|
17
|
+
%i[toolbar_actions_classname]
|
18
|
+
end
|
11
19
|
|
12
|
-
def
|
13
|
-
|
20
|
+
def toolbar_actions_classname
|
21
|
+
raw_attributes_hash[:toolbar_actions_classname]
|
14
22
|
end
|
15
23
|
end
|
16
24
|
end
|
17
25
|
|
18
|
-
Plutonium::ComponentRegistry.register :toolbar, to:
|
26
|
+
Plutonium::ComponentRegistry.register :toolbar, to: PlutoniumUi::ToolbarComponent
|