plutonium 0.10.3 → 0.11.1
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/Rakefile +1 -2
- data/app/assets/application.js.bk +31419 -0
- data/app/assets/plutonium-original.png +0 -0
- data/app/assets/plutonium-white.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/assets/plutonium.png +0 -0
- data/app/views/application/_flash_alerts.html.erb +2 -2
- data/app/views/application/_resource_header.html.erb +261 -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 +83 -0
- data/app/views/components/resource_header/resource_header_component.rb +30 -0
- data/app/views/components/resource_layout/resource_layout_component.html.erb +49 -0
- data/app/views/components/resource_layout/resource_layout_component.rb +41 -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 +12 -45
- data/app/views/layouts/rodauth.html.erb +20 -36
- 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 +44 -0
- data/lib/generators/pu/core/assets/templates/tailwind.config.js +18 -0
- data/lib/generators/pu/core/install/install_generator.rb +4 -1
- 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 +41 -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 +26 -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
|