plutonium 0.14.1 → 0.15.0.pre.rc1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. checksums.yaml +4 -4
  2. data/README copy.md +1 -1
  3. data/README.md +1 -1
  4. data/app/assets/plutonium.css +1 -1
  5. data/app/views/{application → plutonium}/_resource_header.html copy.erb +1 -1
  6. data/app/views/{application → plutonium}/_resource_header.html.erb +1 -1
  7. data/app/views/{application → plutonium}/_resource_sidebar.html.erb +2 -0
  8. data/app/views/resource/_resource_details.html.erb +1 -36
  9. data/app/views/resource/_resource_form.html.erb +1 -5
  10. data/app/views/resource/_resource_table.html.erb +315 -85
  11. data/app/views/resource/edit.html.erb +1 -5
  12. data/app/views/resource/index.html.erb +1 -5
  13. data/app/views/resource/new.html.erb +1 -5
  14. data/app/views/resource/show.html.erb +1 -5
  15. data/config/initializers/pagy.rb +1 -0
  16. data/config/initializers/rabl.rb +27 -20
  17. data/gemfiles/rails_7.gemfile.lock +5 -1
  18. data/lib/generators/pu/core/install/templates/app/controllers/plutonium_controller.rb.tt +2 -0
  19. data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +21 -1
  20. data/lib/generators/pu/core/install/templates/app/definitions/resource_definition.rb.tt +2 -0
  21. data/lib/generators/pu/core/install/templates/app/models/resource_record.rb.tt +0 -2
  22. data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +1 -8
  23. data/lib/generators/pu/eject/shell/shell_generator.rb +2 -2
  24. data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +1 -1
  25. data/lib/generators/pu/lib/plutonium_generators/concerns/logger.rb +1 -1
  26. data/lib/generators/pu/lib/plutonium_generators/generator.rb +5 -3
  27. data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +26 -2
  28. data/lib/generators/pu/pkg/{feature/feature_generator.rb → package/package_generator.rb} +4 -4
  29. data/lib/generators/pu/pkg/{feature → package}/templates/app/controllers/resource_controller.rb.tt +0 -2
  30. data/lib/generators/pu/pkg/package/templates/app/definitions/resource_definition.rb.tt +4 -0
  31. data/lib/generators/pu/pkg/package/templates/app/query_objects/resource_query_object.rb.tt +4 -0
  32. data/lib/generators/pu/pkg/{app/app_generator.rb → portal/portal_generator.rb} +10 -8
  33. data/lib/generators/pu/pkg/{app → portal}/templates/app/controllers/concerns/controller.rb.tt +3 -7
  34. data/lib/generators/pu/pkg/{app → portal}/templates/app/controllers/dashboard_controller.rb.tt +1 -1
  35. data/lib/generators/pu/pkg/portal/templates/app/controllers/plutonium_controller.rb.tt +5 -0
  36. data/lib/generators/pu/pkg/{app/templates/app/controllers/controller.rb.tt → portal/templates/app/controllers/resource_controller.rb.tt} +1 -1
  37. data/lib/generators/pu/pkg/portal/templates/app/definitions/resource_definition.rb.tt +4 -0
  38. data/lib/generators/pu/pkg/{app → portal}/templates/app/views/package/dashboard/index.html.erb +2 -1
  39. data/lib/generators/pu/res/conn/conn_generator.rb +78 -3
  40. data/lib/generators/pu/res/conn/templates/app/controllers/resource_controller.rb.tt +1 -1
  41. data/lib/generators/pu/res/conn/templates/app/definitions/resource_definition.rb.tt +3 -0
  42. data/lib/generators/pu/res/conn/templates/app/policies/resource_policy.rb.tt +29 -1
  43. data/lib/generators/pu/res/conn/templates/app/presenters/resource_presenter.rb.tt +1 -1
  44. data/lib/generators/pu/res/conn/templates/app/query_objects/resource_query_object.rb.tt +1 -1
  45. data/lib/generators/pu/res/model/model_generator.rb +0 -7
  46. data/lib/generators/pu/res/model/templates/model.rb.tt +4 -1
  47. data/lib/generators/pu/res/scaffold/scaffold_generator.rb +22 -4
  48. data/lib/generators/pu/res/scaffold/templates/controller.rb.tt +0 -1
  49. data/lib/generators/pu/res/scaffold/templates/definition.rb.tt +4 -0
  50. data/lib/generators/pu/res/scaffold/templates/policy.rb.tt +2 -2
  51. data/lib/generators/pu/rodauth/templates/app/controllers/rodauth_controller.rb.tt +1 -1
  52. data/lib/generators/pu/rodauth/templates/app/rodauth/account_rodauth_plugin.rb.tt +270 -0
  53. data/lib/plutonium/action/README.md +0 -0
  54. data/lib/plutonium/action/base.rb +103 -0
  55. data/lib/plutonium/action/interactive.rb +117 -0
  56. data/lib/plutonium/action/route_options.rb +65 -0
  57. data/lib/plutonium/action/simple.rb +8 -0
  58. data/lib/plutonium/auth.rb +1 -1
  59. data/lib/plutonium/configuration.rb +0 -8
  60. data/lib/plutonium/core/actions/collection.rb +1 -1
  61. data/lib/plutonium/core/associations/renderers/factory.rb +3 -1
  62. data/lib/plutonium/core/controller.rb +110 -0
  63. data/lib/plutonium/core/controllers/authorizable.rb +12 -35
  64. data/lib/plutonium/core/controllers/bootable.rb +38 -7
  65. data/lib/plutonium/core/controllers/entity_scoping.rb +6 -2
  66. data/lib/plutonium/core/fields/renderers/association_renderer.rb +1 -1
  67. data/lib/plutonium/core/ui/collection.rb +1 -1
  68. data/lib/plutonium/core/ui/detail.rb +1 -1
  69. data/lib/plutonium/core/ui/form.rb +1 -1
  70. data/lib/plutonium/definition/actions.rb +50 -0
  71. data/lib/plutonium/definition/base.rb +92 -0
  72. data/lib/plutonium/definition/config_attr.rb +30 -0
  73. data/lib/plutonium/definition/defineable_props.rb +96 -0
  74. data/lib/plutonium/definition/search.rb +21 -0
  75. data/lib/plutonium/engine/validator.rb +30 -0
  76. data/lib/plutonium/engine.rb +25 -0
  77. data/lib/plutonium/helpers/form_helper.rb +1 -3
  78. data/lib/plutonium/interaction/README.md +369 -0
  79. data/lib/plutonium/interaction/base.rb +75 -0
  80. data/lib/plutonium/interaction/concerns/presentable.rb +61 -0
  81. data/lib/plutonium/interaction/concerns/workflow_dsl.rb +82 -0
  82. data/lib/plutonium/interaction/outcome.rb +129 -0
  83. data/lib/plutonium/interaction/response/base.rb +63 -0
  84. data/lib/plutonium/interaction/response/null.rb +33 -0
  85. data/lib/plutonium/interaction/response/redirect.rb +30 -0
  86. data/lib/plutonium/interaction/response/render.rb +28 -0
  87. data/lib/plutonium/lib/bit_flags.rb +70 -9
  88. data/lib/plutonium/{config → lib}/overlayed_hash.rb +1 -1
  89. data/lib/plutonium/lib/smart_cache.rb +171 -0
  90. data/lib/plutonium/models/has_cents.rb +170 -0
  91. data/lib/plutonium/{pkg/base.rb → package/engine.rb} +10 -2
  92. data/lib/plutonium/{application → portal}/controller.rb +3 -11
  93. data/lib/plutonium/{application → portal}/dynamic_controllers.rb +4 -4
  94. data/lib/plutonium/portal/engine.rb +15 -0
  95. data/lib/plutonium/railtie.rb +33 -1
  96. data/lib/plutonium/reloader.rb +5 -5
  97. data/lib/plutonium/resource/controller.rb +51 -34
  98. data/lib/plutonium/resource/controllers/authorizable.rb +128 -0
  99. data/lib/plutonium/{core → resource}/controllers/crud_actions.rb +23 -22
  100. data/lib/plutonium/resource/controllers/defineable.rb +26 -0
  101. data/lib/plutonium/{core → resource}/controllers/interactive_actions.rb +12 -12
  102. data/lib/plutonium/resource/controllers/presentable.rb +41 -0
  103. data/lib/plutonium/resource/controllers/queryable.rb +44 -0
  104. data/lib/plutonium/resource/definition.rb +6 -0
  105. data/lib/plutonium/resource/policy.rb +25 -13
  106. data/lib/plutonium/resource/query_object.rb +50 -51
  107. data/lib/plutonium/resource/record.rb +6 -89
  108. data/lib/plutonium/resource/register.rb +82 -0
  109. data/lib/plutonium/routing/mapper_extensions.rb +1 -1
  110. data/lib/plutonium/routing/resource_registration.rb +1 -1
  111. data/lib/plutonium/routing/route_set_extensions.rb +6 -18
  112. data/lib/plutonium/ui/action_button.rb +125 -0
  113. data/lib/plutonium/ui/breadcrumbs.rb +163 -0
  114. data/lib/plutonium/ui/component/base.rb +13 -0
  115. data/lib/plutonium/ui/component/behaviour.rb +38 -0
  116. data/lib/plutonium/ui/component/kit.rb +31 -0
  117. data/lib/plutonium/ui/component/methods.rb +54 -0
  118. data/lib/plutonium/ui/display/base.rb +25 -0
  119. data/lib/plutonium/ui/display/component/association.rb +26 -0
  120. data/lib/plutonium/ui/display/resource.rb +77 -0
  121. data/lib/plutonium/ui/display/theme.rb +27 -0
  122. data/lib/plutonium/ui/dyna_frame/content.rb +20 -0
  123. data/lib/plutonium/ui/empty_card.rb +20 -0
  124. data/lib/plutonium/ui/form/base.rb +37 -0
  125. data/lib/plutonium/ui/form/resource.rb +75 -0
  126. data/lib/plutonium/ui/form/theme.rb +42 -0
  127. data/lib/plutonium/ui/page/base.rb +112 -0
  128. data/lib/plutonium/ui/page/edit.rb +23 -0
  129. data/lib/plutonium/ui/page/index.rb +27 -0
  130. data/lib/plutonium/ui/page/new.rb +23 -0
  131. data/lib/plutonium/ui/page/show.rb +27 -0
  132. data/lib/plutonium/ui/page_header.rb +49 -0
  133. data/lib/plutonium/ui/table/base.rb +13 -0
  134. data/lib/plutonium/ui/table/components/pagy_info.rb +70 -0
  135. data/lib/plutonium/ui/table/components/pagy_page_info.rb +70 -0
  136. data/lib/plutonium/ui/table/components/pagy_pagination.rb +105 -0
  137. data/lib/plutonium/ui/table/components/scopes_bar.rb +136 -0
  138. data/lib/plutonium/ui/table/components/search_bar.rb +158 -0
  139. data/lib/plutonium/ui/table/display_theme.rb +21 -0
  140. data/lib/plutonium/ui/table/resource.rb +98 -0
  141. data/lib/plutonium/ui/table/theme.rb +35 -0
  142. data/lib/plutonium/ui.rb +9 -0
  143. data/lib/plutonium/version.rb +5 -1
  144. data/lib/plutonium.rb +14 -1
  145. data/package-lock.json +19 -22
  146. data/package.json +4 -4
  147. data/src/css/plutonium.css +15 -0
  148. data/tailwind.options.js +11 -3
  149. metadata +218 -81
  150. data/lib/generators/pu/core/install/templates/app/presenters/resource_presenter.rb.tt +0 -2
  151. data/lib/generators/pu/core/install/templates/app/query_objects/resource_query_object.rb.tt +0 -2
  152. data/lib/generators/pu/pkg/feature/templates/app/query_objects/resource_query_object.rb.tt +0 -4
  153. data/lib/plutonium/concerns/resource_validatable.rb +0 -34
  154. data/lib/plutonium/config.rb +0 -9
  155. data/lib/plutonium/core/controllers/base.rb +0 -101
  156. data/lib/plutonium/core/controllers/presentable.rb +0 -65
  157. data/lib/plutonium/core/controllers/queryable.rb +0 -28
  158. data/lib/plutonium/pkg/app.rb +0 -35
  159. data/lib/plutonium/pkg/concerns/resource_validatable.rb +0 -36
  160. data/lib/plutonium/pkg/feature.rb +0 -18
  161. data/lib/plutonium/policy/initializer.rb +0 -22
  162. data/lib/plutonium/policy/scope.rb +0 -19
  163. data/lib/plutonium/pundit/context.rb +0 -18
  164. data/lib/plutonium/pundit/policy_finder.rb +0 -25
  165. data/lib/plutonium/resource/policy_context.rb +0 -5
  166. data/lib/plutonium/resource_register.rb +0 -83
  167. data/lib/plutonium/smart_cache.rb +0 -151
  168. /data/app/views/{application → plutonium}/_flash.html.erb +0 -0
  169. /data/app/views/{application → plutonium}/_flash_alerts.html.erb +0 -0
  170. /data/app/views/{application → plutonium}/_flash_toasts.html.erb +0 -0
  171. /data/lib/generators/pu/pkg/{app/templates/app/views/package → package/templates}/.keep +0 -0
  172. /data/lib/generators/pu/pkg/{feature → package}/templates/app/interactions/resource_interaction.rb.tt +0 -0
  173. /data/lib/generators/pu/pkg/{feature → package}/templates/app/models/resource_record.rb.tt +0 -0
  174. /data/lib/generators/pu/pkg/{feature → package}/templates/app/policies/resource_policy.rb.tt +0 -0
  175. /data/lib/generators/pu/pkg/{feature → package}/templates/app/presenters/resource_presenter.rb.tt +0 -0
  176. /data/lib/generators/pu/pkg/{feature → package}/templates/lib/engine.rb.tt +0 -0
  177. /data/lib/generators/pu/pkg/{app → portal}/templates/app/policies/resource_policy.rb.tt +0 -0
  178. /data/lib/generators/pu/pkg/{app → portal}/templates/app/presenters/resource_presenter.rb.tt +0 -0
  179. /data/lib/generators/pu/pkg/{app → portal}/templates/app/query_objects/resource_query_object.rb.tt +0 -0
  180. /data/lib/generators/pu/pkg/{feature/templates → portal/templates/app/views/package}/.keep +0 -0
  181. /data/lib/generators/pu/pkg/{app → portal}/templates/config/routes.rb.tt +0 -0
  182. /data/lib/generators/pu/pkg/{app → portal}/templates/lib/engine.rb.tt +0 -0
@@ -1,92 +1,322 @@
1
- <%# locals: (collection:) -%>
1
+ <%= render build_collection %>
2
2
 
3
- <%
4
- resource_class = collection.resource_class
5
- resources = collection.records.to_a
6
- record_actions = collection.actions.collection_record_actions
7
- search_object = collection.search_object
8
- fields = collection.fields
9
- pager = collection.pager
10
- collection_actions = @collection.actions.collection_actions.permitted_for(current_policy)
11
- table_rounding = search_object.scope_definitions.present? ? :bottom : :all
12
- -%>
3
+ <%#
13
4
 
14
- <%= render_component :table_toolbar, resource_class:, search_object:, actions: collection_actions %>
5
+ <div class="space-y-2 mb-4 mt-6">
6
+ <!-- Search Bar -->
7
+ <div class="p-4 bg-white border border-gray-200 rounded-lg dark:bg-gray-800 dark:border-gray-700 space-y-2">
8
+ <div class="relative">
9
+ <div class="absolute inset-y-0 left-0 flex items-center pl-3 pointer-events-none">
10
+ <svg class="w-5 h-5 text-gray-500 dark:text-gray-400" aria-hidden="true" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
11
+ <path fill-rule="evenodd" d="M8 4a4 4 0 100 8 4 4 0 000-8zM2 8a6 6 0 1110.89 3.476l4.817 4.817a1 1 0 01-1.414 1.414l-4.816-4.816A6 6 0 012 8z" clip-rule="evenodd"></path>
12
+ </svg>
13
+ </div>
14
+ <input type="text" id="table-search" class="block w-full p-2 pl-10 text-sm text-gray-900 border border-gray-300 rounded-lg bg-gray-50 focus:ring-blue-500 focus:border-blue-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="Search for items" oninput="searchTable()">
15
+ </div>
16
+ <div class="flex flex-wrap items-center gap-4">
17
+ <span class="text-sm font-medium text-gray-900 dark:text-white">Filters:</span>
15
18
 
16
- <% if search_object.scope_definitions.present? %>
17
- <%
18
- name = name.to_s
19
- current_scope = resource_query_params[:scope]
20
- %>
21
- <%= render_component :block, rounded: :top do %>
22
- <ul class="text-sm font-medium flex flex-wrap -mb-px">
23
- <li class="me-2">
24
- <% if current_scope.blank? %>
25
- <a class="inline-block p-4 text-primary-600 border-b-2 border-primary-600 rounded-t-lg active dark:text-primary-500 dark:border-primary-500" aria-current="page" href="?<%= search_object.build_url(scope: nil) %>">All</a>
26
- <% else %>
27
- <a class="inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 dark:text-gray-500" href="<%= search_object.build_url(scope: nil) %>">All</a>
28
- <% end %>
29
- </li>
19
+ <select id="category-filter" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
20
+ <option selected value="">All Categories</option>
21
+ <option value="technology">Technology</option>
22
+ <option value="science">Science</option>
23
+ <option value="health">Health</option>
24
+ </select>
30
25
 
31
- <% search_object.scope_definitions.each do |name, definition| %>
32
- <li class="me-2">
33
- <% if name == current_scope %>
34
- <a class="inline-block p-4 text-primary-600 border-b-2 border-primary-600 rounded-t-lg active dark:text-primary-500 dark:border-primary-500" aria-current="page" href="?<%= search_object.build_url(scope: name) %>"><%= name.humanize %></a>
35
- <% else %>
36
- <a class="inline-block p-4 border-b-2 border-transparent rounded-t-lg hover:text-gray-600 hover:border-gray-300 dark:hover:text-gray-300 dark:text-gray-500" href="<%= search_object.build_url(scope: name) %>"><%= name.humanize %></a>
37
- <% end %>
38
- </li>
39
- <% end %>
40
- </ul>
41
- <% end %>
42
- <% end %>
26
+ <div class="flex items-center space-x-2">
27
+ <input type="date" id="start-date" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
28
+ <span class="text-gray-500 dark:text-gray-400">to</span>
29
+ <input type="date" id="end-date" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
30
+ </div>
43
31
 
44
- <%= render_component :block, id: "resource-table-container",
45
- scroll: :x,
46
- rounded: table_rounding,
47
- data: {
48
- controller:"scroll-preserver",
49
- action: "scroll->scroll-preserver#scrolled"
50
- } do %>
51
- <% unless resources.any? %>
52
- <%# empty card %>
53
- <div class="col-12">
54
- <%=
55
- render_component :empty_card, message: "No #{resource_name_plural(resource_class).downcase} match your query" do
56
- if current_policy.create?
57
- render_component :button, label: "Create #{resource_name(resource_class)}",
58
- to: resource_url_for(resource_class, action: :new),
59
- color: :primary
60
- end
61
- end
62
- %>
32
+ <select id="author-filter" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
33
+ <option selected value="">All Authors</option>
34
+ <option value="john-doe">John Doe</option>
35
+ <option value="jane-smith">Jane Smith</option>
36
+ </select>
37
+
38
+ <button onclick="applyFilters()" class="inline-flex items-center text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-4 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800">
39
+ <svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
40
+ <path fill-rule="evenodd" d="M3 3a1 1 0 011-1h12a1 1 0 011 1v3a1 1 0 01-.293.707L12 11.414V15a1 1 0 01-.293.707l-2 2A1 1 0 018 17v-5.586L3.293 6.707A1 1 0 013 6V3z" clip-rule="evenodd"></path>
41
+ </svg>
42
+ Apply Filters
43
+ </button>
44
+
45
+ <button onclick="clearFilters()" class="inline-flex items-center text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-4 py-2 dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700">
46
+ <svg class="w-4 h-4 mr-2" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
47
+ <path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path>
48
+ </svg>
49
+ Clear Filters
50
+ </button>
51
+ </div>
52
+ </div>
53
+
54
+ <!-- Scopes and Bulk Actions -->
55
+ <div class="flex flex-wrap justify-between items-center gap-4 p-4 bg-white border border-gray-200 rounded-lg dark:bg-gray-800 dark:border-gray-700">
56
+ <!-- Scopes -->
57
+ <div class="flex flex-wrap items-center gap-2">
58
+ <button id="all-scope" onclick="filterTable('all')" class="px-4 py-2 text-sm font-medium text-gray-900 bg-gray-100 border border-gray-200 rounded-lg hover:bg-gray-200 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-600">
59
+ All
60
+ </button>
61
+ <button id="featured-scope" onclick="filterTable('featured')" class="px-4 py-2 text-sm font-medium text-gray-900 bg-gray-100 border border-gray-200 rounded-lg hover:bg-gray-200 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-600">
62
+ Featured
63
+ </button>
64
+ <button id="draft-scope" onclick="filterTable('draft')" class="px-4 py-2 text-sm font-medium text-gray-900 bg-gray-100 border border-gray-200 rounded-lg hover:bg-gray-200 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-600">
65
+ Draft <span class="ml-1 text-gray-500 dark:text-gray-400">(1)</span>
66
+ </button>
67
+ <button id="published-scope" onclick="filterTable('published')" class="px-4 py-2 text-sm font-medium text-gray-900 bg-gray-100 border border-gray-200 rounded-lg hover:bg-gray-200 hover:text-blue-700 focus:z-10 focus:ring-2 focus:ring-blue-700 focus:text-blue-700 dark:bg-gray-700 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-600">
68
+ Published <span class="ml-1 text-gray-500 dark:text-gray-400">(2)</span>
69
+ </button>
70
+ </div>
71
+
72
+ <!-- Bulk Actions -->
73
+ <div class="flex flex-wrap items-center gap-2">
74
+ <button onclick="bulkAction('delete')" class="inline-flex items-center px-3 py-2 text-sm font-medium text-white bg-red-700 rounded-lg hover:bg-red-800 focus:ring-4 focus:outline-none focus:ring-red-300 dark:bg-red-600 dark:hover:bg-red-700 dark:focus:ring-red-800">
75
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
76
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path>
77
+ </svg>
78
+ Delete Selected
79
+ </button>
80
+ <button onclick="bulkAction('archive')" class="inline-flex items-center px-3 py-2 text-sm font-medium text-white bg-yellow-700 rounded-lg hover:bg-yellow-800 focus:ring-4 focus:outline-none focus:ring-yellow-300 dark:bg-yellow-600 dark:hover:bg-yellow-700 dark:focus:ring-yellow-800">
81
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
82
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 8h14M5 8a2 2 0 110-4h14a2 2 0 110 4M5 8v10a2 2 0 002 2h10a2 2 0 002-2V8m-9 4h4"></path>
83
+ </svg>
84
+ Archive Selected
85
+ </button>
86
+ <button id="dropdownActionButton" data-dropdown-toggle="dropdownAction" class="inline-flex items-center text-gray-500 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-3 py-2 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700" type="button">
87
+ <span class="sr-only">Action button</span>
88
+ More Actions
89
+ <svg class="w-2.5 h-2.5 ml-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
90
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
91
+ </svg>
92
+ </button>
93
+ </div>
94
+ </div>
95
+ </div>
96
+
97
+ <!-- Table -->
98
+ <div class="relative overflow-x-auto shadow-md sm:rounded-lg">
99
+ <table class="w-full text-sm text-left rtl:text-right text-gray-500 dark:text-gray-400">
100
+ <caption class="p-5 text-lg font-semibold text-left rtl:text-right text-gray-900 bg-white dark:text-white dark:bg-gray-800">
101
+ <div class="flex justify-between items-center">
102
+ <div>
103
+ Manage your blog posts
104
+ <p class="mt-1 text-sm font-normal text-gray-500 dark:text-gray-400">Manage your blog posts.</p>
105
+ </div>
106
+ <div class="flex space-x-2">
107
+ <button type="button" class="px-4 py-2 text-sm font-medium text-blue-700 hover:text-blue-800 focus:z-10 focus:outline-none focus:ring-2 focus:ring-blue-700 dark:text-blue-400 dark:hover:text-blue-500">
108
+ <span class="flex items-center">
109
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
110
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M5 13l4 4L19 7"></path>
111
+ </svg>
112
+ Select All
113
+ </span>
114
+ </button>
115
+ <button type="button" class="px-4 py-2 text-sm font-medium text-red-700 hover:text-red-800 focus:z-10 focus:outline-none focus:ring-2 focus:ring-red-700 dark:text-red-400 dark:hover:text-red-500">
116
+ <span class="flex items-center">
117
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg">
118
+ <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M6 18L18 6M6 6l12 12"></path>
119
+ </svg>
120
+ Deselect All
121
+ </span>
122
+ </button>
123
+ </div>
124
+ </div>
125
+ </caption>
126
+ <thead class="text-xs text-gray-700 uppercase bg-gray-50 dark:bg-gray-700 dark:text-gray-400">
127
+ <tr>
128
+ <th scope="col" class="px-6 py-3">
129
+ <input type="checkbox" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
130
+ </th>
131
+ <th scope="col" class="px-6 py-3">Title</th>
132
+ <th scope="col" class="px-6 py-3">Slug</th>
133
+ <th scope="col" class="px-6 py-3">Is featured</th>
134
+ <th scope="col" class="px-6 py-3">Actions</th>
135
+ </tr>
136
+ </thead>
137
+ <tbody>
138
+ <tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
139
+ <td class="px-6 py-4">
140
+ <input type="checkbox" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
141
+ </td>
142
+ <th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">What is Plutonium?</th>
143
+ <td class="px-6 py-4">what-is-plutonium</td>
144
+ <td class="px-6 py-4"><span class="text-green-600 dark:text-green-400">✓</span></td>
145
+ <td class="px-6 py-4">
146
+ <div class="flex items-center space-x-2">
147
+ <button type="button" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800 flex items-center">
148
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path></svg>
149
+ View
150
+ </button>
151
+ <button type="button" class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
152
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path></svg>
153
+ Edit
154
+ </button>
155
+ <button type="button" class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
156
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg>
157
+ Delete
158
+ </button>
159
+ <button id="dropdownDefaultButton" data-dropdown-toggle="dropdown" class="text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-3 py-2 text-center inline-flex items-center dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700" type="button">
160
+ More
161
+ <svg class="w-2.5 h-2.5 ml-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
162
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
163
+ </svg>
164
+ </button>
165
+ <div id="dropdown" class="z-10 hidden absolute bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700">
166
+ <ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
167
+ <li>
168
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Duplicate</a>
169
+ </li>
170
+ <li>
171
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Archive</a>
172
+ </li>
173
+ <li>
174
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Download</a>
175
+ </li>
176
+ </ul>
177
+ </div>
178
+ </div>
179
+ </td>
180
+ </tr>
181
+ <tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
182
+ <td class="px-6 py-4">
183
+ <input type="checkbox" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
184
+ </td>
185
+ <th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">Top 5 best features of Plutonium</th>
186
+ <td class="px-6 py-4">top-5-features</td>
187
+ <td class="px-6 py-4"><span class="text-green-600 dark:text-green-400">✓</span></td>
188
+ <td class="px-6 py-4">
189
+ <div class="flex items-center space-x-2">
190
+ <button type="button" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800 flex items-center">
191
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path></svg>
192
+ View
193
+ </button>
194
+ <button type="button" class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
195
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path></svg>
196
+ Edit
197
+ </button>
198
+ <button type="button" class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
199
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg>
200
+ Delete
201
+ </button>
202
+ <button id="dropdownDefaultButton" data-dropdown-toggle="dropdown" class="text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-3 py-2 text-center inline-flex items-center dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700" type="button">
203
+ More
204
+ <svg class="w-2.5 h-2.5 ml-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
205
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
206
+ </svg>
207
+ </button>
208
+ <div id="dropdown" class="z-10 hidden absolute bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700">
209
+ <ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
210
+ <li>
211
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Duplicate</a>
212
+ </li>
213
+ <li>
214
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Archive</a>
215
+ </li>
216
+ <li>
217
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Download</a>
218
+ </li>
219
+ </ul>
220
+ </div>
221
+ </div>
222
+ </td>
223
+ </tr>
224
+ <tr class="bg-white border-b dark:bg-gray-800 dark:border-gray-700">
225
+ <td class="px-6 py-4">
226
+ <input type="checkbox" class="w-4 h-4 text-blue-600 bg-gray-100 border-gray-300 rounded focus:ring-blue-500 dark:focus:ring-blue-600 dark:ring-offset-gray-800 focus:ring-2 dark:bg-gray-700 dark:border-gray-600">
227
+ </td>
228
+ <th scope="row" class="px-6 py-4 font-medium text-gray-900 whitespace-nowrap dark:text-white">Customizing Plutonium's UI with a theme</th>
229
+ <td class="px-6 py-4">theme-guide</td>
230
+ <td class="px-6 py-4"><span class="text-green-600 dark:text-green-400">✓</span></td>
231
+ <td class="px-6 py-4">
232
+ <div class="flex items-center space-x-2">
233
+ <button type="button" class="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:ring-blue-300 font-medium rounded-lg text-sm px-3 py-2 dark:bg-blue-600 dark:hover:bg-blue-700 focus:outline-none dark:focus:ring-blue-800 flex items-center">
234
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"></path><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M2.458 12C3.732 7.943 7.523 5 12 5c4.478 0 8.268 2.943 9.542 7-1.274 4.057-5.064 7-9.542 7-4.477 0-8.268-2.943-9.542-7z"></path></svg>
235
+ View
236
+ </button>
237
+ <button type="button" class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
238
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15.232 5.232l3.536 3.536m-2.036-5.036a2.5 2.5 0 113.536 3.536L6.5 21.036H3v-3.572L16.732 3.732z"></path></svg>
239
+ Edit
240
+ </button>
241
+ <button type="button" class="py-2 px-3 flex items-center text-sm font-medium text-center text-gray-900 focus:outline-none bg-white rounded-lg border border-gray-200 hover:bg-gray-100 hover:text-blue-700 focus:z-10 focus:ring-4 focus:ring-gray-200 dark:focus:ring-gray-700 dark:bg-gray-800 dark:text-gray-400 dark:border-gray-600 dark:hover:text-white dark:hover:bg-gray-700">
242
+ <svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24" xmlns="http://www.w3.org/2000/svg"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M19 7l-.867 12.142A2 2 0 0116.138 21H7.862a2 2 0 01-1.995-1.858L5 7m5 4v6m4-6v6m1-10V4a1 1 0 00-1-1h-4a1 1 0 00-1 1v3M4 7h16"></path></svg>
243
+ Delete
244
+ </button>
245
+ <button id="dropdownDefaultButton" data-dropdown-toggle="dropdown" class="text-gray-900 bg-white border border-gray-300 focus:outline-none hover:bg-gray-100 focus:ring-4 focus:ring-gray-200 font-medium rounded-lg text-sm px-3 py-2 text-center inline-flex items-center dark:bg-gray-800 dark:text-white dark:border-gray-600 dark:hover:bg-gray-700 dark:hover:border-gray-600 dark:focus:ring-gray-700" type="button">
246
+ More
247
+ <svg class="w-2.5 h-2.5 ml-2.5" aria-hidden="true" xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 10 6">
248
+ <path stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="m1 1 4 4 4-4"/>
249
+ </svg>
250
+ </button>
251
+ <div id="dropdown" class="z-10 hidden absolute bg-white divide-y divide-gray-100 rounded-lg shadow w-44 dark:bg-gray-700">
252
+ <ul class="py-2 text-sm text-gray-700 dark:text-gray-200" aria-labelledby="dropdownDefaultButton">
253
+ <li>
254
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Duplicate</a>
255
+ </li>
256
+ <li>
257
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Archive</a>
258
+ </li>
259
+ <li>
260
+ <a href="#" class="block px-4 py-2 hover:bg-gray-100 dark:hover:bg-gray-600 dark:hover:text-white">Download</a>
261
+ </li>
262
+ </ul>
263
+ </div>
264
+ </div>
265
+ </td>
266
+ </tr>
267
+ </tbody>
268
+ </table>
269
+ </div>
270
+
271
+ <!-- display control -->
272
+ <div class="flex flex-col md:flex-row justify-between items-center mt-4 text-sm text-gray-500 dark:text-gray-400">
273
+ <div>
274
+ Showing 1 to 5 of 50 results
275
+ </div>
276
+ <div class="flex items-center space-x-2 mt-2 md:mt-0">
277
+ <label for="perPage" class="mr-2">Per page</label>
278
+ <select id="perPage" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
279
+ <option selected>5</option>
280
+ <option>10</option>
281
+ <option>25</option>
282
+ <option>50</option>
283
+ </select>
284
+ </div>
285
+ </div>
286
+
287
+ <!-- pagination -->
288
+ <div class="flex justify-center mt-4">
289
+ <nav aria-label="Page navigation example">
290
+ <ul class="inline-flex -space-x-px text-sm">
291
+ <li>
292
+ <a href="#" class="flex items-center justify-center px-3 h-8 ms-0 leading-tight text-gray-500 bg-white border border-e-0 border-gray-300 rounded-s-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">Previous</a>
293
+ </li>
294
+ <li>
295
+ <a href="#" aria-current="page" class="flex items-center justify-center px-3 h-8 text-blue-600 border border-gray-300 bg-blue-50 hover:bg-blue-100 hover:text-blue-700 dark:border-gray-700 dark:bg-gray-700 dark:text-white">1</a>
296
+ </li>
297
+ <li>
298
+ <a href="#" class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">2</a>
299
+ </li>
300
+ <li>
301
+ <a href="#" class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">3</a>
302
+ </li>
303
+ <li>
304
+ <a href="#" class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">4</a>
305
+ </li>
306
+ <li>
307
+ <a href="#" class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">...</a>
308
+ </li>
309
+ <li>
310
+ <a href="#" class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">9</a>
311
+ </li>
312
+ <li>
313
+ <a href="#" class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">10</a>
314
+ </li>
315
+ <li>
316
+ <a href="#" class="flex items-center justify-center px-3 h-8 leading-tight text-gray-500 bg-white border border-gray-300 rounded-e-lg hover:bg-gray-100 hover:text-gray-700 dark:bg-gray-800 dark:border-gray-700 dark:text-gray-400 dark:hover:bg-gray-700 dark:hover:text-white">Next</a>
317
+ </li>
318
+ </ul>
319
+ </nav>
63
320
  </div>
64
- <% else %>
65
- <%# table %>
66
- <%= render_component :table, rows: resources do |table| %>
67
- <% table.with_actions do |resource| %>
68
- <% record_actions.permitted_for(policy(resource)).values.each do |action| %>
69
- <%= table_action_button resource, action %>
70
- <% end %>
71
- <% end %>
72
321
 
73
- <% fields.each do |name, field| %>
74
- <%#
75
- TODO:
76
- For now, we are hacking around the need to call #with before #label
77
- This proves there's an issue with the rendering api.
78
- While I think of an elegant solution, this works for now.
79
- %>
80
- <% field.with(record: resources[0]) %>
81
- <% table.column(name:, label: field.label, search_object: search_object) do |resource| %>
82
- <% field.with(record: resource) %>
83
- <%= render field %>
84
- <% end %>
85
- <% end %>
86
- <% end %>
87
- <%# pagination %>
88
- <% if pager.present? %>
89
- <%= render_component :pagination, pager: pager %>
90
- <% end %>
91
- <% end %>
92
- <% end %>
322
+ %>
@@ -1,5 +1 @@
1
- <%= render_component :breadcrumbs, resource_class:, parent: current_parent, resource: @form.record %>
2
-
3
- <%= render_component :dyna_frame_content do %>
4
- <%= render "resource_form", form: @form %>
5
- <% end %>
1
+ <%= render current_definition.edit_page_class.new %>
@@ -1,5 +1 @@
1
- <%= render_component :breadcrumbs, resource_class:, parent: current_parent %>
2
-
3
- <%= render_component :dyna_frame_content do %>
4
- <%= render "resource_table", collection: @collection %>
5
- <% end %>
1
+ <%= render current_definition.index_page_class.new %>
@@ -1,5 +1 @@
1
- <%= render_component :breadcrumbs, resource_class:, parent: current_parent, resource: @form.record %>
2
-
3
- <%= render_component :dyna_frame_content do %>
4
- <%= render "resource_form", form: @form %>
5
- <% end %>
1
+ <%= render current_definition.new_page_class.new %>
@@ -1,5 +1 @@
1
- <%= render_component :breadcrumbs, resource_class:, parent: current_parent, resource: @detail.record %>
2
-
3
- <%= render_component :dyna_frame_content do %>
4
- <%= render "resource_details", details: @detail %>
5
- <% end %>
1
+ <%= render current_definition.show_page_class.new %>
@@ -2,3 +2,4 @@ require "pagy"
2
2
  require "pagy/extras/overflow"
3
3
  require "pagy/extras/trim"
4
4
  require "pagy/extras/headers"
5
+ require "pagy/extras/limit"
@@ -30,32 +30,39 @@ Rabl.configure do |config|
30
30
  # config.camelize_keys = :upper # Defaults to false
31
31
  end
32
32
 
33
- # Monkey Patch Rabl source lookup to make it compatible with Rails view lookup
33
+ # Extend Rabl source lookup to make it compatible with Rails view lookup
34
34
  module Rabl
35
35
  module Sources
36
- private
36
+ module RailsViewLookupExtension
37
+ private
37
38
 
38
- # Returns the rabl template path for Rails
39
- def fetch_rails_source(file, _options = {})
40
- # use Rails template resolution mechanism if possible (find_template)
41
- source_format = request_format if defined?(request_format)
39
+ # Returns the rabl template path for Rails
40
+ def fetch_rails_source(file, options = {})
41
+ # use Rails template resolution mechanism if possible (find_template)
42
+ source_format = request_format if defined?(request_format)
42
43
 
43
- lookup_proc = lambda do |partial|
44
- context_scope.lookup_context.find(file, context_scope.lookup_context.prefixes, partial, [],
45
- {formats: [source_format]})
46
- end
47
- template = begin
48
- lookup_proc.call(false)
49
- rescue
50
- nil
51
- end
52
- template ||= begin
53
- lookup_proc.call(true)
54
- rescue
55
- nil
44
+ lookup_proc = lambda do |partial|
45
+ context_scope.lookup_context.find(file, context_scope.lookup_context.prefixes, partial, [],
46
+ {formats: [source_format]})
47
+ end
48
+
49
+ template = begin
50
+ lookup_proc.call(false)
51
+ rescue
52
+ nil
53
+ end
54
+
55
+ template ||= begin
56
+ lookup_proc.call(true)
57
+ rescue
58
+ nil
59
+ end
60
+
61
+ template&.identifier
56
62
  end
57
- template&.identifier
58
63
  end
64
+
65
+ prepend RailsViewLookupExtension
59
66
  end
60
67
  end
61
68
 
@@ -1,7 +1,8 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- plutonium (0.12.13)
4
+ plutonium (0.15.0)
5
+ action_policy (~> 0.7.0)
5
6
  active_interaction (~> 5.3)
6
7
  dry-initializer (~> 3.1)
7
8
  listen (~> 3.8)
@@ -19,6 +20,8 @@ PATH
19
20
  GEM
20
21
  remote: https://rubygems.org/
21
22
  specs:
23
+ action_policy (0.7.0)
24
+ ruby-next-core (>= 1.0)
22
25
  actioncable (7.1.3.4)
23
26
  actionpack (= 7.1.3.4)
24
27
  activesupport (= 7.1.3.4)
@@ -253,6 +256,7 @@ GEM
253
256
  rubocop-performance (1.21.0)
254
257
  rubocop (>= 1.48.1, < 2.0)
255
258
  rubocop-ast (>= 1.31.1, < 2.0)
259
+ ruby-next-core (1.0.3)
256
260
  ruby-progressbar (1.13.0)
257
261
  semantic_range (3.0.0)
258
262
  simple_form (5.3.1)
@@ -0,0 +1,2 @@
1
+ class PlutoniumController < <%= ApplicationController < ActionController::Base ? "ApplicationController" : "ActionController::Base" %>
2
+ end
@@ -1,3 +1,23 @@
1
- class ResourceController < ApplicationController
1
+ class ResourceController < PlutoniumController
2
2
  include Plutonium::Resource::Controller
3
+ <%- if !ApplicationController.new.respond_to?(:current_user, true) -%>
4
+
5
+ private def current_user
6
+ raise NotImplementedError, "#{self.class}#current_user must return a non nil value"
7
+ end
8
+ helper_method :current_user
9
+ <%- elsif !ApplicationController._helper_methods.include?(:current_user) -%>
10
+
11
+ helper_method :current_user
12
+ <%- end -%>
13
+ <%- if !ApplicationController.new.respond_to?(:logout_url, true) -%>
14
+
15
+ private def logout_url
16
+ # return a logout url to render a logout link
17
+ end
18
+ helper_method :logout_url
19
+ <%- elsif !ApplicationController._helper_methods.include?(:logout_url) -%>
20
+
21
+ helper_method :logout_url
22
+ <%- end -%>
3
23
  end
@@ -0,0 +1,2 @@
1
+ class ResourceDefinition < Plutonium::Resource::Definition
2
+ end
@@ -1,5 +1,3 @@
1
1
  class ResourceRecord < ApplicationRecord
2
- include Plutonium::Resource::Record
3
-
4
2
  self.abstract_class = true
5
3
  end
@@ -4,12 +4,5 @@ Plutonium.configure do |config|
4
4
  config.load_defaults 1.0
5
5
 
6
6
  # config.assets.logo = "logo.png"
7
- # Configure plutonium above this
8
- end
9
-
10
- Rails.application.config.to_prepare do
11
- # Register components here
12
-
13
- # e.g
14
- # Plutonium::Core::Fields::Renderers::Factory.map_type :mapped_collection, to: Fields::Renderers::MappedCollectionRenderer
7
+ # Configure plutonium above.
15
8
  end
@@ -16,8 +16,8 @@ module Pu
16
16
  def start
17
17
  destination_dir = (destination_app == "main_app") ? "app/views/" : "packages/#{destination_app}/app/views"
18
18
  [
19
- "application/_resource_header.html.erb",
20
- "application/_resource_sidebar.html.erb"
19
+ "plutonium/_resource_header.html.erb",
20
+ "plutonium/_resource_sidebar.html.erb"
21
21
  ].each do |file|
22
22
  copy_file Plutonium.root.join("app", "views", file), Rails.root.join(destination_dir, file)
23
23
  end