plutonium 0.14.1 → 0.15.0.pre.rc1

Sign up to get free protection for your applications and to get access to all the features.
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