easy-admin-rails 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +28 -0
- data/Rakefile +8 -0
- data/app/assets/builds/easy_admin.base.js +43505 -0
- data/app/assets/builds/easy_admin.base.js.map +7 -0
- data/app/assets/builds/easy_admin.css +6141 -0
- data/app/assets/config/easy_admin_manifest.js +1 -0
- data/app/assets/images/jsoneditor-icons.svg +749 -0
- data/app/assets/stylesheets/easy_admin/application.tailwind.css +390 -0
- data/app/components/easy_admin/base_component.rb +35 -0
- data/app/components/easy_admin/batch_action_bar_component.rb +125 -0
- data/app/components/easy_admin/batch_action_form_component.rb +124 -0
- data/app/components/easy_admin/combined_filters_component.rb +232 -0
- data/app/components/easy_admin/confirmation_modal_component.rb +61 -0
- data/app/components/easy_admin/context_menu_component.rb +161 -0
- data/app/components/easy_admin/dashboards/base_card_component.rb +152 -0
- data/app/components/easy_admin/dashboards/card_error_component.rb +23 -0
- data/app/components/easy_admin/dashboards/card_factory.rb +90 -0
- data/app/components/easy_admin/dashboards/card_stream_component.rb +22 -0
- data/app/components/easy_admin/dashboards/cards/base_card_component.rb +54 -0
- data/app/components/easy_admin/dashboards/cards/chart_card_component.rb +175 -0
- data/app/components/easy_admin/dashboards/cards/custom_card_component.rb +50 -0
- data/app/components/easy_admin/dashboards/cards/metric_card_component.rb +164 -0
- data/app/components/easy_admin/dashboards/cards/table_card_component.rb +148 -0
- data/app/components/easy_admin/dashboards/chart_card_component.rb +44 -0
- data/app/components/easy_admin/dashboards/metric_card_component.rb +56 -0
- data/app/components/easy_admin/dashboards/refresh_stream_component.rb +279 -0
- data/app/components/easy_admin/dashboards/show_component.rb +163 -0
- data/app/components/easy_admin/dashboards/table_card_component.rb +52 -0
- data/app/components/easy_admin/date_picker_component.rb +188 -0
- data/app/components/easy_admin/fields/base_component.rb +101 -0
- data/app/components/easy_admin/fields/belongs_to_edit_modal_component.rb +117 -0
- data/app/components/easy_admin/fields/form/belongs_to_component.rb +82 -0
- data/app/components/easy_admin/fields/form/boolean_component.rb +100 -0
- data/app/components/easy_admin/fields/form/date_component.rb +55 -0
- data/app/components/easy_admin/fields/form/datetime_component.rb +55 -0
- data/app/components/easy_admin/fields/form/email_component.rb +55 -0
- data/app/components/easy_admin/fields/form/file_component.rb +190 -0
- data/app/components/easy_admin/fields/form/has_many_component.rb +416 -0
- data/app/components/easy_admin/fields/form/json_component.rb +81 -0
- data/app/components/easy_admin/fields/form/number_component.rb +55 -0
- data/app/components/easy_admin/fields/form/select_component.rb +326 -0
- data/app/components/easy_admin/fields/form/text_component.rb +55 -0
- data/app/components/easy_admin/fields/form/textarea_component.rb +54 -0
- data/app/components/easy_admin/fields/index/belongs_to_component.rb +93 -0
- data/app/components/easy_admin/fields/index/boolean_component.rb +29 -0
- data/app/components/easy_admin/fields/index/date_component.rb +13 -0
- data/app/components/easy_admin/fields/index/datetime_component.rb +13 -0
- data/app/components/easy_admin/fields/index/email_component.rb +24 -0
- data/app/components/easy_admin/fields/index/filters/base_component.rb +48 -0
- data/app/components/easy_admin/fields/index/filters/boolean_component.rb +96 -0
- data/app/components/easy_admin/fields/index/filters/date_component.rb +182 -0
- data/app/components/easy_admin/fields/index/filters/number_component.rb +30 -0
- data/app/components/easy_admin/fields/index/filters/select_component.rb +101 -0
- data/app/components/easy_admin/fields/index/filters/string_component.rb +32 -0
- data/app/components/easy_admin/fields/index/json_component.rb +23 -0
- data/app/components/easy_admin/fields/index/number_component.rb +20 -0
- data/app/components/easy_admin/fields/index/select_component.rb +25 -0
- data/app/components/easy_admin/fields/index/text_component.rb +20 -0
- data/app/components/easy_admin/fields/inline_edit_modal_component.rb +135 -0
- data/app/components/easy_admin/fields/inline_edit_trigger_component.rb +144 -0
- data/app/components/easy_admin/fields/show/belongs_to_component.rb +93 -0
- data/app/components/easy_admin/fields/show/boolean_component.rb +21 -0
- data/app/components/easy_admin/fields/show/date_component.rb +13 -0
- data/app/components/easy_admin/fields/show/datetime_component.rb +13 -0
- data/app/components/easy_admin/fields/show/email_component.rb +19 -0
- data/app/components/easy_admin/fields/show/file_component.rb +304 -0
- data/app/components/easy_admin/fields/show/has_many_component.rb +192 -0
- data/app/components/easy_admin/fields/show/json_component.rb +45 -0
- data/app/components/easy_admin/fields/show/number_component.rb +20 -0
- data/app/components/easy_admin/fields/show/select_component.rb +25 -0
- data/app/components/easy_admin/fields/show/text_component.rb +17 -0
- data/app/components/easy_admin/fields/show/textarea_component.rb +26 -0
- data/app/components/easy_admin/filters_component.rb +120 -0
- data/app/components/easy_admin/form_tabs_component.rb +166 -0
- data/app/components/easy_admin/infinite_scroll_component.rb +82 -0
- data/app/components/easy_admin/lazy_chart_card_component.rb +128 -0
- data/app/components/easy_admin/lazy_metric_card_component.rb +76 -0
- data/app/components/easy_admin/modal_frame_component.rb +26 -0
- data/app/components/easy_admin/navbar_component.rb +226 -0
- data/app/components/easy_admin/notification_component.rb +83 -0
- data/app/components/easy_admin/pagination_component.rb +188 -0
- data/app/components/easy_admin/quick_filters_component.rb +65 -0
- data/app/components/easy_admin/resource_pagination_component.rb +14 -0
- data/app/components/easy_admin/resources/index_component.rb +211 -0
- data/app/components/easy_admin/resources/index_frame_component.rb +88 -0
- data/app/components/easy_admin/resources/show_page_actions_component.rb +324 -0
- data/app/components/easy_admin/resources/table_cell_component.rb +145 -0
- data/app/components/easy_admin/resources/table_component.rb +206 -0
- data/app/components/easy_admin/resources/table_row_component.rb +160 -0
- data/app/components/easy_admin/row_action_form_component.rb +127 -0
- data/app/components/easy_admin/scopes_component.rb +224 -0
- data/app/components/easy_admin/settings_sidebar_component.rb +140 -0
- data/app/components/easy_admin/show_layout_component.rb +600 -0
- data/app/components/easy_admin/sidebar_component.rb +174 -0
- data/app/components/easy_admin/turbo/response_component.rb +40 -0
- data/app/components/easy_admin/turbo/stream_component.rb +28 -0
- data/app/controllers/easy_admin/application_controller.rb +66 -0
- data/app/controllers/easy_admin/batch_actions_controller.rb +166 -0
- data/app/controllers/easy_admin/confirmation_modal_controller.rb +20 -0
- data/app/controllers/easy_admin/dashboard_controller.rb +6 -0
- data/app/controllers/easy_admin/dashboards_controller.rb +123 -0
- data/app/controllers/easy_admin/passwords_controller.rb +15 -0
- data/app/controllers/easy_admin/registrations_controller.rb +52 -0
- data/app/controllers/easy_admin/resources_controller.rb +907 -0
- data/app/controllers/easy_admin/row_actions_controller.rb +216 -0
- data/app/controllers/easy_admin/sessions_controller.rb +32 -0
- data/app/controllers/easy_admin/settings_controller.rb +94 -0
- data/app/helpers/easy_admin/application_helper.rb +4 -0
- data/app/helpers/easy_admin/dashboards_helper.rb +121 -0
- data/app/helpers/easy_admin/fields_helper.rb +27 -0
- data/app/helpers/easy_admin/pagy_helper.rb +30 -0
- data/app/helpers/easy_admin/resources_helper.rb +39 -0
- data/app/javascript/easy_admin/application.js +12 -0
- data/app/javascript/easy_admin/controllers/batch_modal_controller.js +66 -0
- data/app/javascript/easy_admin/controllers/batch_selection_controller.js +223 -0
- data/app/javascript/easy_admin/controllers/chart_controller.js +216 -0
- data/app/javascript/easy_admin/controllers/collapsible_filters_controller.js +118 -0
- data/app/javascript/easy_admin/controllers/confirmation_modal_controller.js +64 -0
- data/app/javascript/easy_admin/controllers/context_menu_controller.js +227 -0
- data/app/javascript/easy_admin/controllers/date_picker_controller.js +309 -0
- data/app/javascript/easy_admin/controllers/dropdown_controller.js +63 -0
- data/app/javascript/easy_admin/controllers/event_emitter_controller.js +19 -0
- data/app/javascript/easy_admin/controllers/file_controller.js +121 -0
- data/app/javascript/easy_admin/controllers/form_tabs_controller.js +100 -0
- data/app/javascript/easy_admin/controllers/has_many_search_controller.js +76 -0
- data/app/javascript/easy_admin/controllers/infinite_scroll_controller.js +174 -0
- data/app/javascript/easy_admin/controllers/ios_alert_controller.js +195 -0
- data/app/javascript/easy_admin/controllers/jsoneditor_controller.js +88 -0
- data/app/javascript/easy_admin/controllers/modal_controller.js +75 -0
- data/app/javascript/easy_admin/controllers/navbar_scroll_controller.js +76 -0
- data/app/javascript/easy_admin/controllers/notification_controller.js +48 -0
- data/app/javascript/easy_admin/controllers/row_action_controller.js +124 -0
- data/app/javascript/easy_admin/controllers/row_modal_controller.js +59 -0
- data/app/javascript/easy_admin/controllers/select_field_controller.js +618 -0
- data/app/javascript/easy_admin/controllers/settings_button_controller.js +8 -0
- data/app/javascript/easy_admin/controllers/settings_sidebar_controller.js +186 -0
- data/app/javascript/easy_admin/controllers/sidebar_controller.js +102 -0
- data/app/javascript/easy_admin/controllers/sidebar_mobile_controller.js +23 -0
- data/app/javascript/easy_admin/controllers/sidebar_nav_controller.js +96 -0
- data/app/javascript/easy_admin/controllers/table_controller.js +28 -0
- data/app/javascript/easy_admin/controllers/table_row_controller.js +16 -0
- data/app/javascript/easy_admin/controllers/toggle_switch_controller.js +22 -0
- data/app/javascript/easy_admin/controllers/turbo_stream_redirect.js +9 -0
- data/app/javascript/easy_admin/controllers.js +54 -0
- data/app/javascript/easy_admin.base.js +4 -0
- data/app/models/easy_admin/admin_user.rb +53 -0
- data/app/models/easy_admin/application_record.rb +5 -0
- data/app/views/easy_admin/dashboard/index.html.erb +3 -0
- data/app/views/easy_admin/dashboards/show.html.erb +7 -0
- data/app/views/easy_admin/passwords/edit.html.erb +42 -0
- data/app/views/easy_admin/passwords/new.html.erb +41 -0
- data/app/views/easy_admin/registrations/new.html.erb +65 -0
- data/app/views/easy_admin/resources/_redirect.turbo_stream.erb +3 -0
- data/app/views/easy_admin/resources/_table_rows.html.erb +46 -0
- data/app/views/easy_admin/resources/edit.html.erb +151 -0
- data/app/views/easy_admin/resources/index.html.erb +12 -0
- data/app/views/easy_admin/resources/index.turbo_stream.erb +139 -0
- data/app/views/easy_admin/resources/index_frame.html.erb +142 -0
- data/app/views/easy_admin/resources/new.html.erb +100 -0
- data/app/views/easy_admin/resources/show.html.erb +31 -0
- data/app/views/easy_admin/sessions/new.html.erb +55 -0
- data/app/views/easy_admin/settings/_form.html.erb +51 -0
- data/app/views/easy_admin/settings/index.html.erb +53 -0
- data/app/views/layouts/easy_admin/application.html.erb +48 -0
- data/app/views/layouts/easy_admin/auth.html.erb +34 -0
- data/config/initializers/easy_admin_card_factory.rb +27 -0
- data/config/initializers/pagy.rb +15 -0
- data/config/initializers/rack_mini_profiler.rb +67 -0
- data/config/routes.rb +70 -0
- data/db/migrate/20250101000001_create_easy_admin_admin_users.rb +45 -0
- data/lib/easy-admin.rb +32 -0
- data/lib/easy_admin/action.rb +159 -0
- data/lib/easy_admin/batch_action.rb +134 -0
- data/lib/easy_admin/configuration.rb +75 -0
- data/lib/easy_admin/dashboard.rb +110 -0
- data/lib/easy_admin/dashboard_registry.rb +30 -0
- data/lib/easy_admin/delete_action.rb +22 -0
- data/lib/easy_admin/engine.rb +54 -0
- data/lib/easy_admin/field.rb +118 -0
- data/lib/easy_admin/resource.rb +806 -0
- data/lib/easy_admin/resource_registry.rb +22 -0
- data/lib/easy_admin/types/json_type.rb +25 -0
- data/lib/easy_admin/version.rb +3 -0
- data/lib/generators/easy_admin/auth_generator.rb +69 -0
- data/lib/generators/easy_admin/card/card_generator.rb +94 -0
- data/lib/generators/easy_admin/card/templates/card_component.rb.erb +127 -0
- data/lib/generators/easy_admin/card/templates/card_component_spec.rb.erb +122 -0
- data/lib/generators/easy_admin/install/templates/easy_admin.rb +31 -0
- data/lib/generators/easy_admin/install_generator.rb +25 -0
- data/lib/generators/easy_admin/rbac/rbac_generator.rb +244 -0
- data/lib/generators/easy_admin/rbac/templates/add_rbac_to_admin_users.rb +23 -0
- data/lib/generators/easy_admin/rbac/templates/super_admin.rb +34 -0
- data/lib/generators/easy_admin/resource_generator.rb +43 -0
- data/lib/generators/easy_admin/templates/AUTH_README +35 -0
- data/lib/generators/easy_admin/templates/README +27 -0
- data/lib/generators/easy_admin/templates/create_easy_admin_admin_users.rb +45 -0
- data/lib/generators/easy_admin/templates/devise.rb +267 -0
- data/lib/generators/easy_admin/templates/easy_admin.rb +24 -0
- data/lib/generators/easy_admin/templates/resource.rb +29 -0
- data/lib/tasks/easy_admin_tasks.rake +4 -0
- metadata +445 -0
@@ -0,0 +1,41 @@
|
|
1
|
+
<!-- Form -->
|
2
|
+
<div class="p-10">
|
3
|
+
<%= form_for(resource, as: resource_name, url: password_path(resource_name), html: { method: :post, class: "space-y-8" }) do |f| %>
|
4
|
+
|
5
|
+
<!-- Input Field Container -->
|
6
|
+
<div class="space-y-4">
|
7
|
+
<!-- Email Field -->
|
8
|
+
<div class="relative">
|
9
|
+
<%= f.email_field :email, autofocus: true, autocomplete: "email",
|
10
|
+
class: "w-full px-6 py-5 bg-gray-50/80 border-0 text-gray-900 placeholder-gray-400 focus:bg-gray-100/80 focus:ring-0 focus:outline-none text-base rounded-2xl transition-colors duration-200 font-medium",
|
11
|
+
placeholder: "Email address" %>
|
12
|
+
</div>
|
13
|
+
</div>
|
14
|
+
|
15
|
+
<!-- Helper Text -->
|
16
|
+
<div class="text-sm text-gray-500 text-center font-medium">
|
17
|
+
Enter your email and we'll send you a reset link
|
18
|
+
</div>
|
19
|
+
|
20
|
+
<!-- Submit Button -->
|
21
|
+
<div class="pt-4">
|
22
|
+
<%= f.submit "Send Reset Instructions",
|
23
|
+
class: "w-full bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 text-white font-bold py-5 px-6 rounded-2xl transition-all duration-200 focus:outline-none focus:ring-4 focus:ring-blue-500/30 text-base shadow-xl shadow-blue-500/20 active:scale-[0.98]" %>
|
24
|
+
</div>
|
25
|
+
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<!-- Links -->
|
29
|
+
<div class="text-center pt-6 space-y-3">
|
30
|
+
<%= link_to "Back to Sign In", new_session_path(resource_name),
|
31
|
+
class: "block text-base text-blue-500 hover:text-blue-600 font-bold transition-colors duration-200" %>
|
32
|
+
|
33
|
+
<% if devise_mapping.registerable? && controller_name != 'registrations' %>
|
34
|
+
<div class="text-base text-gray-600">
|
35
|
+
Don't have an account?
|
36
|
+
<%= link_to "Create account", new_registration_path(resource_name),
|
37
|
+
class: "text-blue-500 hover:text-blue-600 font-bold ml-2 transition-colors duration-200" %>
|
38
|
+
</div>
|
39
|
+
<% end %>
|
40
|
+
</div>
|
41
|
+
</div>
|
@@ -0,0 +1,65 @@
|
|
1
|
+
<!-- Form -->
|
2
|
+
<div class="p-10">
|
3
|
+
<%= form_for(resource, as: resource_name, url: registration_path(resource_name), local: true, html: { class: "space-y-8" }) do |f| %>
|
4
|
+
|
5
|
+
<!-- Input Fields Container -->
|
6
|
+
<div class="space-y-4">
|
7
|
+
<!-- First Name Field -->
|
8
|
+
<div class="relative">
|
9
|
+
<%= f.text_field :first_name, autofocus: true, autocomplete: "given-name",
|
10
|
+
class: "w-full px-6 py-5 bg-gray-50/80 border-0 text-gray-900 placeholder-gray-400 focus:bg-gray-100/80 focus:ring-0 focus:outline-none text-base rounded-2xl transition-colors duration-200 font-medium",
|
11
|
+
placeholder: "First name" %>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<!-- Last Name Field -->
|
15
|
+
<div class="relative">
|
16
|
+
<%= f.text_field :last_name, autocomplete: "family-name",
|
17
|
+
class: "w-full px-6 py-5 bg-gray-50/80 border-0 text-gray-900 placeholder-gray-400 focus:bg-gray-100/80 focus:ring-0 focus:outline-none text-base rounded-2xl transition-colors duration-200 font-medium",
|
18
|
+
placeholder: "Last name" %>
|
19
|
+
</div>
|
20
|
+
|
21
|
+
<!-- Email Field -->
|
22
|
+
<div class="relative">
|
23
|
+
<%= f.email_field :email, autocomplete: "email",
|
24
|
+
class: "w-full px-6 py-5 bg-gray-50/80 border-0 text-gray-900 placeholder-gray-400 focus:bg-gray-100/80 focus:ring-0 focus:outline-none text-base rounded-2xl transition-colors duration-200 font-medium",
|
25
|
+
placeholder: "Email address" %>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<!-- Password Field -->
|
29
|
+
<div class="relative">
|
30
|
+
<%= f.password_field :password, autocomplete: "new-password",
|
31
|
+
class: "w-full px-6 py-5 bg-gray-50/80 border-0 text-gray-900 placeholder-gray-400 focus:bg-gray-100/80 focus:ring-0 focus:outline-none text-base rounded-2xl transition-colors duration-200 font-medium",
|
32
|
+
placeholder: "Password" %>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<!-- Password Confirmation Field -->
|
36
|
+
<div class="relative">
|
37
|
+
<%= f.password_field :password_confirmation, autocomplete: "new-password",
|
38
|
+
class: "w-full px-6 py-5 bg-gray-50/80 border-0 text-gray-900 placeholder-gray-400 focus:bg-gray-100/80 focus:ring-0 focus:outline-none text-base rounded-2xl transition-colors duration-200 font-medium",
|
39
|
+
placeholder: "Confirm password" %>
|
40
|
+
</div>
|
41
|
+
</div>
|
42
|
+
|
43
|
+
<% if @minimum_password_length %>
|
44
|
+
<div class="text-sm text-gray-500 text-center font-medium">
|
45
|
+
Password must be at least <%= @minimum_password_length %> characters
|
46
|
+
</div>
|
47
|
+
<% end %>
|
48
|
+
|
49
|
+
<!-- Submit Button -->
|
50
|
+
<div class="pt-4">
|
51
|
+
<%= f.submit "Create Account",
|
52
|
+
class: "w-full bg-gradient-to-r from-blue-500 to-blue-600 hover:from-blue-600 hover:to-blue-700 text-white font-bold py-5 px-6 rounded-2xl transition-all duration-200 focus:outline-none focus:ring-4 focus:ring-blue-500/30 text-base shadow-xl shadow-blue-500/20 active:scale-[0.98]" %>
|
53
|
+
</div>
|
54
|
+
|
55
|
+
<% end %>
|
56
|
+
|
57
|
+
<!-- Links -->
|
58
|
+
<div class="text-center pt-6">
|
59
|
+
<div class="text-base text-gray-600">
|
60
|
+
Already have an account?
|
61
|
+
<%= link_to "Sign in", new_session_path(resource_name),
|
62
|
+
class: "text-blue-500 hover:text-blue-600 font-bold ml-2 transition-colors duration-200" %>
|
63
|
+
</div>
|
64
|
+
</div>
|
65
|
+
</div>
|
@@ -0,0 +1,46 @@
|
|
1
|
+
<% records.each do |record| %>
|
2
|
+
<tr class="hover:bg-gray-100 cursor-pointer transition-colors duration-150"
|
3
|
+
onclick="window.location='<%= easy_admin.resource_path(resource_class.route_key, record) %>'">
|
4
|
+
<% resource_class.index_fields.each_with_index do |field, index| %>
|
5
|
+
<td class="whitespace-nowrap px-6 py-4 text-sm <%= 'mobile-hide' if index > 2 %>">
|
6
|
+
<div class="text-gray-900 font-medium">
|
7
|
+
<%== render_field(field, action: :index, value: record.public_send(field[:name]), record: record) %>
|
8
|
+
</div>
|
9
|
+
</td>
|
10
|
+
<% end %>
|
11
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
|
12
|
+
<div class="flex items-center justify-end space-x-2 sm:mobile-actions">
|
13
|
+
<%= link_to easy_admin.resource_path(resource_class.route_key, record),
|
14
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-blue-600 hover:text-blue-800 hover:bg-blue-50 rounded-lg transition-colors duration-150",
|
15
|
+
onclick: "event.stopPropagation()",
|
16
|
+
title: "View" do %>
|
17
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
18
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
19
|
+
<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"/>
|
20
|
+
</svg>
|
21
|
+
<% end %>
|
22
|
+
<%= link_to easy_admin.edit_resource_path(resource_class.route_key, record),
|
23
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-green-600 hover:text-green-800 hover:bg-green-50 rounded-lg transition-colors duration-150",
|
24
|
+
onclick: "event.stopPropagation()",
|
25
|
+
title: "Edit" do %>
|
26
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
27
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
|
28
|
+
</svg>
|
29
|
+
<% end %>
|
30
|
+
<%= link_to easy_admin.resource_path(resource_class.route_key, record),
|
31
|
+
method: :delete,
|
32
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-red-600 hover:text-red-800 hover:bg-red-50 rounded-lg transition-colors duration-150",
|
33
|
+
onclick: "event.stopPropagation()",
|
34
|
+
title: "Delete",
|
35
|
+
data: {
|
36
|
+
confirm: "Are you sure you want to delete this #{resource_class.singular_title.downcase}?",
|
37
|
+
method: :delete
|
38
|
+
} do %>
|
39
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
40
|
+
<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"/>
|
41
|
+
</svg>
|
42
|
+
<% end %>
|
43
|
+
</div>
|
44
|
+
</td>
|
45
|
+
</tr>
|
46
|
+
<% end %>
|
@@ -0,0 +1,151 @@
|
|
1
|
+
<% content_for :title, "Edit #{@resource_class.singular_title}" %>
|
2
|
+
|
3
|
+
<!-- Page Header -->
|
4
|
+
<div class="mb-4 sm:mb-6">
|
5
|
+
<!-- Mobile Header -->
|
6
|
+
<div class="sm:hidden mb-4">
|
7
|
+
<div class="flex items-center justify-between mb-3">
|
8
|
+
<h1 class="text-lg font-semibold text-gray-900">Edit <%= @resource_class.singular_title %></h1>
|
9
|
+
<div class="flex space-x-2">
|
10
|
+
<%= link_to easy_admin.resource_path(@resource_class.route_key, @record),
|
11
|
+
class: "inline-flex items-center px-3 py-2 border border-gray-300 rounded-md text-xs font-medium text-gray-700 bg-white hover:bg-gray-50" do %>
|
12
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
13
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
14
|
+
<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"/>
|
15
|
+
</svg>
|
16
|
+
<% end %>
|
17
|
+
|
18
|
+
<%= link_to easy_admin.resources_path(@resource_class.route_key),
|
19
|
+
class: "inline-flex items-center px-3 py-2 border border-gray-300 rounded-md text-xs font-medium text-gray-700 bg-white hover:bg-gray-50" do %>
|
20
|
+
<svg class="w-4 h-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
21
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m0 7h18"/>
|
22
|
+
</svg>
|
23
|
+
<% end %>
|
24
|
+
</div>
|
25
|
+
</div>
|
26
|
+
|
27
|
+
<!-- Mobile Breadcrumb -->
|
28
|
+
<nav class="text-xs text-gray-500">
|
29
|
+
<%= link_to @resource_class.title, easy_admin.resources_path(@resource_class.route_key), class: "hover:text-gray-700" %>
|
30
|
+
/ <%= link_to (@record.respond_to?(:name) ? @record.name : "##{@record.id}"), easy_admin.resource_path(@resource_class.route_key, @record), class: "hover:text-gray-700" %>
|
31
|
+
/ Edit
|
32
|
+
</nav>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<!-- Desktop Header -->
|
36
|
+
<div class="hidden sm:flex items-center justify-between">
|
37
|
+
<nav class="flex" aria-label="Breadcrumb">
|
38
|
+
<ol class="inline-flex items-center space-x-1 md:space-x-3">
|
39
|
+
<li>
|
40
|
+
<%= link_to easy_admin.resources_path(@resource_class.route_key),
|
41
|
+
class: "text-gray-500 hover:text-gray-700 text-sm font-medium" do %>
|
42
|
+
<%= @resource_class.title %>
|
43
|
+
<% end %>
|
44
|
+
</li>
|
45
|
+
<li>
|
46
|
+
<div class="flex items-center">
|
47
|
+
<svg class="w-4 h-4 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
48
|
+
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
|
49
|
+
</svg>
|
50
|
+
<%= link_to easy_admin.resource_path(@resource_class.route_key, @record),
|
51
|
+
class: "ml-1 text-gray-500 hover:text-gray-700 text-sm font-medium" do %>
|
52
|
+
<%= @record.respond_to?(:name) ? @record.name : "##{@record.id}" %>
|
53
|
+
<% end %>
|
54
|
+
</div>
|
55
|
+
</li>
|
56
|
+
<li>
|
57
|
+
<div class="flex items-center">
|
58
|
+
<svg class="w-4 h-4 text-gray-400" fill="currentColor" viewBox="0 0 20 20">
|
59
|
+
<path fill-rule="evenodd" d="M7.293 14.707a1 1 0 010-1.414L10.586 10 7.293 6.707a1 1 0 011.414-1.414l4 4a1 1 0 010 1.414l-4 4a1 1 0 01-1.414 0z" clip-rule="evenodd"/>
|
60
|
+
</svg>
|
61
|
+
<span class="ml-1 text-sm font-medium text-gray-900">Edit</span>
|
62
|
+
</div>
|
63
|
+
</li>
|
64
|
+
</ol>
|
65
|
+
</nav>
|
66
|
+
|
67
|
+
<div class="flex space-x-3">
|
68
|
+
<%= link_to easy_admin.resource_path(@resource_class.route_key, @record),
|
69
|
+
class: "inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" do %>
|
70
|
+
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
71
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
72
|
+
<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"/>
|
73
|
+
</svg>
|
74
|
+
View
|
75
|
+
<% end %>
|
76
|
+
|
77
|
+
<%= link_to easy_admin.resources_path(@resource_class.route_key),
|
78
|
+
class: "inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" do %>
|
79
|
+
<svg class="w-4 h-4 mr-2" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
80
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 19l-7-7m0 0l7-7m0 7h18"/>
|
81
|
+
</svg>
|
82
|
+
Back to <%= @resource_class.title %>
|
83
|
+
<% end %>
|
84
|
+
</div>
|
85
|
+
</div>
|
86
|
+
</div>
|
87
|
+
|
88
|
+
<!-- Form Container -->
|
89
|
+
<div class="max-w-4xl mx-auto">
|
90
|
+
<%= form_with model: @record, url: easy_admin.resource_path(@resource_class.route_key, @record),
|
91
|
+
method: :patch, local: true, multipart: true, class: "space-y-6" do |form| %>
|
92
|
+
|
93
|
+
<!-- Error Messages -->
|
94
|
+
<% if @record.errors.any? %>
|
95
|
+
<div class="bg-red-50 border border-red-200 rounded-md p-4">
|
96
|
+
<div class="flex">
|
97
|
+
<div class="flex-shrink-0">
|
98
|
+
<svg class="h-5 w-5 text-red-400" fill="currentColor" viewBox="0 0 20 20">
|
99
|
+
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"/>
|
100
|
+
</svg>
|
101
|
+
</div>
|
102
|
+
<div class="ml-3">
|
103
|
+
<h3 class="text-sm font-medium text-red-800">
|
104
|
+
<%= pluralize(@record.errors.count, "error") %> prohibited this <%= @resource_class.singular_title.downcase %> from being saved:
|
105
|
+
</h3>
|
106
|
+
<div class="mt-2 text-sm text-red-700">
|
107
|
+
<ul class="list-disc pl-5 space-y-1">
|
108
|
+
<% @record.errors.full_messages.each do |message| %>
|
109
|
+
<li><%= message %></li>
|
110
|
+
<% end %>
|
111
|
+
</ul>
|
112
|
+
</div>
|
113
|
+
</div>
|
114
|
+
</div>
|
115
|
+
</div>
|
116
|
+
<% end %>
|
117
|
+
|
118
|
+
<!-- Form Fields -->
|
119
|
+
<% if @resource_class.has_form_tabs? %>
|
120
|
+
<%= EasyAdmin::FormTabsComponent.new(resource_class: @resource_class, form: form).call.html_safe %>
|
121
|
+
<% else %>
|
122
|
+
<!-- Default Single Card Layout -->
|
123
|
+
<div class="bg-white shadow-sm rounded-lg border border-gray-200">
|
124
|
+
<div class="px-4 py-5 sm:p-6">
|
125
|
+
<h3 class="text-lg font-medium leading-6 text-gray-900 mb-6">
|
126
|
+
<%= @resource_class.singular_title %> Information
|
127
|
+
</h3>
|
128
|
+
|
129
|
+
<div class="grid grid-cols-1 gap-6">
|
130
|
+
<% @resource_class.form_fields.each do |field| %>
|
131
|
+
<div>
|
132
|
+
<%= render_field(field, action: :form, form: form) %>
|
133
|
+
</div>
|
134
|
+
<% end %>
|
135
|
+
</div>
|
136
|
+
</div>
|
137
|
+
</div>
|
138
|
+
<% end %>
|
139
|
+
|
140
|
+
<!-- Action Buttons -->
|
141
|
+
<div class="flex items-center justify-end space-x-3 pt-6">
|
142
|
+
<%= link_to easy_admin.resource_path(@resource_class.route_key, @record),
|
143
|
+
class: "inline-flex items-center px-4 py-2 border border-gray-300 rounded-md shadow-sm text-sm font-medium text-gray-700 bg-white hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" do %>
|
144
|
+
Cancel
|
145
|
+
<% end %>
|
146
|
+
|
147
|
+
<%= form.submit "Update #{@resource_class.singular_title}",
|
148
|
+
class: "inline-flex items-center px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500" %>
|
149
|
+
</div>
|
150
|
+
<% end %>
|
151
|
+
</div>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
<% content_for :title, @resource_class.title %>
|
2
|
+
|
3
|
+
<%== EasyAdmin::Resources::IndexComponent.new(
|
4
|
+
resource_class: @resource_class,
|
5
|
+
current_scope: @current_scope,
|
6
|
+
scope_counts: @scope_counts || {},
|
7
|
+
current_params: params.permit(:search, :scope, :sort, :direction, :period, :page, q: {}),
|
8
|
+
search_params: params[:q] || {},
|
9
|
+
current_period: @current_period,
|
10
|
+
current_user: current_admin_user
|
11
|
+
).call %>
|
12
|
+
|
@@ -0,0 +1,139 @@
|
|
1
|
+
<%= turbo_stream.replace "table-frame" do %>
|
2
|
+
<%= turbo_frame_tag "table-frame" do %>
|
3
|
+
<!-- Striped Table -->
|
4
|
+
<div class="mt-8 flow-root">
|
5
|
+
<div class="mobile-table-wrapper -mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
6
|
+
<div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
7
|
+
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 md:rounded-lg">
|
8
|
+
<table class="table-striped min-w-full divide-y divide-gray-300">
|
9
|
+
<thead class="bg-gray-50">
|
10
|
+
<tr>
|
11
|
+
<% @resource_class.index_fields.each_with_index do |field, index| %>
|
12
|
+
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wide <%= 'mobile-hide' if index > 2 %>">
|
13
|
+
<% if field[:sortable] %>
|
14
|
+
<div class="flex items-center justify-between">
|
15
|
+
<%= link_to field[:label], request.params.merge(sort: field[:name], direction: params[:direction] == 'asc' ? 'desc' : 'asc'),
|
16
|
+
class: "group hover:text-gray-900 transition-colors duration-150" do %>
|
17
|
+
<%= field[:label] %>
|
18
|
+
<% end %>
|
19
|
+
<span class="ml-2 flex-none text-gray-400 hover:text-gray-600">
|
20
|
+
<% if params[:sort] == field[:name].to_s %>
|
21
|
+
<% if params[:direction] == 'asc' %>
|
22
|
+
<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
23
|
+
<path fill-rule="evenodd" d="M14.77 12.79a.75.75 0 01-1.06-.02L10 8.832 6.29 12.77a.75.75 0 11-1.08-1.04l4.25-4.5a.75.75 0 011.08 0l4.25 4.5a.75.75 0 01-.02 1.06z" clip-rule="evenodd"/>
|
24
|
+
</svg>
|
25
|
+
<% else %>
|
26
|
+
<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
27
|
+
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd"/>
|
28
|
+
</svg>
|
29
|
+
<% end %>
|
30
|
+
<% else %>
|
31
|
+
<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
32
|
+
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd"/>
|
33
|
+
</svg>
|
34
|
+
<% end %>
|
35
|
+
</span>
|
36
|
+
</div>
|
37
|
+
<% else %>
|
38
|
+
<%= field[:label] %>
|
39
|
+
<% end %>
|
40
|
+
</th>
|
41
|
+
<% end %>
|
42
|
+
<th scope="col" class="relative px-6 py-3">
|
43
|
+
<span class="sr-only">Actions</span>
|
44
|
+
</th>
|
45
|
+
</tr>
|
46
|
+
</thead>
|
47
|
+
<tbody id="records-container" class="divide-y divide-gray-200 bg-white">
|
48
|
+
<% @records.each do |record| %>
|
49
|
+
<tr class="hover:bg-gray-100 cursor-pointer transition-colors duration-150"
|
50
|
+
onclick="window.location='<%= easy_admin.resource_path(@resource_class.route_key, record) %>'">
|
51
|
+
<% @resource_class.index_fields.each_with_index do |field, index| %>
|
52
|
+
<td class="whitespace-nowrap px-6 py-4 text-sm <%= 'mobile-hide' if index > 2 %>">
|
53
|
+
<div class="text-gray-900 font-medium">
|
54
|
+
<%== render_field(field, action: :index, value: record.public_send(field[:name]), record: record) %>
|
55
|
+
</div>
|
56
|
+
</td>
|
57
|
+
<% end %>
|
58
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
|
59
|
+
<div class="flex items-center justify-end space-x-2 sm:mobile-actions">
|
60
|
+
<%= link_to easy_admin.resource_path(@resource_class.route_key, record),
|
61
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-blue-600 hover:text-blue-800 hover:bg-blue-50 rounded-lg transition-colors duration-150",
|
62
|
+
onclick: "event.stopPropagation()",
|
63
|
+
title: "View" do %>
|
64
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
65
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
66
|
+
<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"/>
|
67
|
+
</svg>
|
68
|
+
<% end %>
|
69
|
+
<%= link_to easy_admin.edit_resource_path(@resource_class.route_key, record),
|
70
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-green-600 hover:text-green-800 hover:bg-green-50 rounded-lg transition-colors duration-150",
|
71
|
+
onclick: "event.stopPropagation()",
|
72
|
+
title: "Edit" do %>
|
73
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
74
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
|
75
|
+
</svg>
|
76
|
+
<% end %>
|
77
|
+
<%= link_to easy_admin.resource_path(@resource_class.route_key, record),
|
78
|
+
method: :delete,
|
79
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-red-600 hover:text-red-800 hover:bg-red-50 rounded-lg transition-colors duration-150",
|
80
|
+
onclick: "event.stopPropagation()",
|
81
|
+
title: "Delete",
|
82
|
+
data: {
|
83
|
+
confirm: "Are you sure you want to delete this #{@resource_class.singular_title.downcase}?",
|
84
|
+
method: :delete
|
85
|
+
} do %>
|
86
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
87
|
+
<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"/>
|
88
|
+
</svg>
|
89
|
+
<% end %>
|
90
|
+
</div>
|
91
|
+
</td>
|
92
|
+
</tr>
|
93
|
+
<% end %>
|
94
|
+
</tbody>
|
95
|
+
</table>
|
96
|
+
</div>
|
97
|
+
</div>
|
98
|
+
</div>
|
99
|
+
</div>
|
100
|
+
|
101
|
+
<!-- Pagination within the turbo frame -->
|
102
|
+
<div id="infinite-scroll-container">
|
103
|
+
<% if @resource_class.respond_to?(:infinite_scroll_enabled?) && @resource_class.infinite_scroll_enabled? %>
|
104
|
+
<%== EasyAdmin::InfiniteScrollComponent.new(
|
105
|
+
pagy: @pagy,
|
106
|
+
resource_class: @resource_class,
|
107
|
+
current_params: params.permit(:search, :scope, :sort, :direction, :period),
|
108
|
+
current_path: request.path
|
109
|
+
).call %>
|
110
|
+
<% else %>
|
111
|
+
<%== EasyAdmin::ResourcePaginationComponent.new(
|
112
|
+
pagy: @pagy,
|
113
|
+
resource_class: @resource_class,
|
114
|
+
request_params: params
|
115
|
+
).call %>
|
116
|
+
<% end %>
|
117
|
+
</div>
|
118
|
+
|
119
|
+
<!-- Empty state within the turbo frame -->
|
120
|
+
<% if @records.empty? && @pagy.page == 1 %>
|
121
|
+
<div class="text-center py-12">
|
122
|
+
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
123
|
+
<path vector-effect="non-scaling-stroke" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2z"/>
|
124
|
+
</svg>
|
125
|
+
<h3 class="mt-2 text-sm font-semibold text-gray-900">No <%= @resource_class.title.downcase %></h3>
|
126
|
+
<p class="mt-1 text-sm text-gray-500">Get started by creating a new <%= @resource_class.singular_title.downcase %>.</p>
|
127
|
+
<div class="mt-6">
|
128
|
+
<%= link_to easy_admin.new_resource_path(@resource_class.route_key),
|
129
|
+
class: "inline-flex items-center rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600" do %>
|
130
|
+
<svg class="-ml-0.5 mr-1.5 h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
131
|
+
<path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"/>
|
132
|
+
</svg>
|
133
|
+
New <%= @resource_class.singular_title %>
|
134
|
+
<% end %>
|
135
|
+
</div>
|
136
|
+
</div>
|
137
|
+
<% end %>
|
138
|
+
<% end %>
|
139
|
+
<% end %>
|
@@ -0,0 +1,142 @@
|
|
1
|
+
<turbo-frame id="table-frame">
|
2
|
+
<!-- Striped Table -->
|
3
|
+
<div class="mt-8 flow-root">
|
4
|
+
<div class="mobile-table-wrapper -mx-4 -my-2 overflow-x-auto sm:-mx-6 lg:-mx-8">
|
5
|
+
<div class="inline-block min-w-full py-2 align-middle sm:px-6 lg:px-8">
|
6
|
+
<div class="overflow-hidden shadow ring-1 ring-black ring-opacity-5 md:rounded-lg">
|
7
|
+
<table class="table-striped min-w-full divide-y divide-gray-300">
|
8
|
+
<thead class="bg-gray-50">
|
9
|
+
<tr>
|
10
|
+
<% @resource_class.index_fields.each_with_index do |field, index| %>
|
11
|
+
<th scope="col" class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wide <%= 'mobile-hide' if index > 2 %>">
|
12
|
+
<% if field[:sortable] %>
|
13
|
+
<div class="flex items-center justify-between">
|
14
|
+
<%
|
15
|
+
# Determine next direction: if currently sorting by this field and direction is 'asc', toggle to 'desc'
|
16
|
+
# Otherwise default to 'asc' for new sort or when toggling from 'desc'
|
17
|
+
next_direction = (params[:sort] == field[:name].to_s && params[:direction] == 'asc') ? 'desc' : 'asc'
|
18
|
+
%>
|
19
|
+
<%= link_to url_for(request.params.merge(sort: field[:name], direction: next_direction)),
|
20
|
+
class: "group hover:text-gray-900 transition-colors duration-150" do %>
|
21
|
+
<%= field[:label] %>
|
22
|
+
<% end %>
|
23
|
+
<span class="ml-2 flex-none text-gray-400 hover:text-gray-600">
|
24
|
+
<% if params[:sort] == field[:name].to_s %>
|
25
|
+
<% if params[:direction] == 'asc' %>
|
26
|
+
<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
27
|
+
<path fill-rule="evenodd" d="M14.77 12.79a.75.75 0 01-1.06-.02L10 8.832 6.29 12.77a.75.75 0 11-1.08-1.04l4.25-4.5a.75.75 0 011.08 0l4.25 4.5a.75.75 0 01-.02 1.06z" clip-rule="evenodd"/>
|
28
|
+
</svg>
|
29
|
+
<% else %>
|
30
|
+
<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
31
|
+
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd"/>
|
32
|
+
</svg>
|
33
|
+
<% end %>
|
34
|
+
<% else %>
|
35
|
+
<svg class="h-4 w-4" viewBox="0 0 20 20" fill="currentColor">
|
36
|
+
<path fill-rule="evenodd" d="M5.23 7.21a.75.75 0 011.06.02L10 11.168l3.71-3.938a.75.75 0 111.08 1.04l-4.25 4.5a.75.75 0 01-1.08 0l-4.25-4.5a.75.75 0 01.02-1.06z" clip-rule="evenodd"/>
|
37
|
+
</svg>
|
38
|
+
<% end %>
|
39
|
+
</span>
|
40
|
+
</div>
|
41
|
+
<% else %>
|
42
|
+
<%= field[:label] %>
|
43
|
+
<% end %>
|
44
|
+
</th>
|
45
|
+
<% end %>
|
46
|
+
<th scope="col" class="relative px-6 py-3">
|
47
|
+
<span class="sr-only">Actions</span>
|
48
|
+
</th>
|
49
|
+
</tr>
|
50
|
+
</thead>
|
51
|
+
<tbody id="records-container" class="divide-y divide-gray-200 bg-white">
|
52
|
+
<% @records.each do |record| %>
|
53
|
+
<tr class="hover:bg-gray-100 cursor-pointer transition-colors duration-150"
|
54
|
+
onclick="window.location='<%= easy_admin.resource_path(@resource_class.route_key, record) %>'">
|
55
|
+
<% @resource_class.index_fields.each_with_index do |field, index| %>
|
56
|
+
<td class="whitespace-nowrap px-6 py-4 text-sm <%= 'mobile-hide' if index > 2 %>">
|
57
|
+
<div class="text-gray-900 font-medium">
|
58
|
+
<%== render_field(field, action: :index, value: record.public_send(field[:name]), record: record) %>
|
59
|
+
</div>
|
60
|
+
</td>
|
61
|
+
<% end %>
|
62
|
+
<td class="relative whitespace-nowrap py-4 pl-3 pr-4 text-right text-sm font-medium sm:pr-6">
|
63
|
+
<div class="flex items-center justify-end space-x-2 sm:mobile-actions">
|
64
|
+
<%= link_to easy_admin.resource_path(@resource_class.route_key, record),
|
65
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-blue-600 hover:text-blue-800 hover:bg-blue-50 rounded-lg transition-colors duration-150",
|
66
|
+
onclick: "event.stopPropagation()",
|
67
|
+
title: "View" do %>
|
68
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
69
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 12a3 3 0 11-6 0 3 3 0 016 0z"/>
|
70
|
+
<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"/>
|
71
|
+
</svg>
|
72
|
+
<% end %>
|
73
|
+
<%= link_to easy_admin.edit_resource_path(@resource_class.route_key, record),
|
74
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-green-600 hover:text-green-800 hover:bg-green-50 rounded-lg transition-colors duration-150",
|
75
|
+
onclick: "event.stopPropagation()",
|
76
|
+
title: "Edit" do %>
|
77
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
78
|
+
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M11 5H6a2 2 0 00-2 2v11a2 2 0 002 2h11a2 2 0 002-2v-5m-1.414-9.414a2 2 0 112.828 2.828L11.828 15H9v-2.828l8.586-8.586z"/>
|
79
|
+
</svg>
|
80
|
+
<% end %>
|
81
|
+
<%= link_to easy_admin.resource_path(@resource_class.route_key, record),
|
82
|
+
method: :delete,
|
83
|
+
class: "inline-flex items-center justify-center w-8 h-8 text-red-600 hover:text-red-800 hover:bg-red-50 rounded-lg transition-colors duration-150",
|
84
|
+
onclick: "event.stopPropagation()",
|
85
|
+
title: "Delete",
|
86
|
+
data: {
|
87
|
+
confirm: "Are you sure you want to delete this #{@resource_class.singular_title.downcase}?",
|
88
|
+
method: :delete
|
89
|
+
} do %>
|
90
|
+
<svg class="h-4 w-4" fill="none" stroke="currentColor" viewBox="0 0 24 24">
|
91
|
+
<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"/>
|
92
|
+
</svg>
|
93
|
+
<% end %>
|
94
|
+
</div>
|
95
|
+
</td>
|
96
|
+
</tr>
|
97
|
+
<% end %>
|
98
|
+
</tbody>
|
99
|
+
</table>
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
</div>
|
103
|
+
</div>
|
104
|
+
|
105
|
+
<!-- Pagination within the turbo frame -->
|
106
|
+
<div id="infinite-scroll-container">
|
107
|
+
<% if @resource_class.respond_to?(:infinite_scroll_enabled?) && @resource_class.infinite_scroll_enabled? %>
|
108
|
+
<%== EasyAdmin::InfiniteScrollComponent.new(
|
109
|
+
pagy: @pagy,
|
110
|
+
resource_class: @resource_class,
|
111
|
+
current_params: params.permit(:search, :scope, :sort, :direction, :period, :page, q: {}),
|
112
|
+
current_path: request.path
|
113
|
+
).call %>
|
114
|
+
<% else %>
|
115
|
+
<%== EasyAdmin::ResourcePaginationComponent.new(
|
116
|
+
pagy: @pagy,
|
117
|
+
resource_class: @resource_class,
|
118
|
+
request_params: params
|
119
|
+
).call %>
|
120
|
+
<% end %>
|
121
|
+
</div>
|
122
|
+
|
123
|
+
<!-- Empty state within the turbo frame -->
|
124
|
+
<% if @records.empty? && @pagy.page == 1 %>
|
125
|
+
<div class="text-center py-12">
|
126
|
+
<svg class="mx-auto h-12 w-12 text-gray-400" fill="none" viewBox="0 0 24 24" stroke="currentColor">
|
127
|
+
<path vector-effect="non-scaling-stroke" stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 13h6m-3-3v6m-9 1V7a2 2 0 012-2h6l2 2h6a2 2 0 012 2v6a2 2 0 01-2 2H5a2 2 0 01-2-2z"/>
|
128
|
+
</svg>
|
129
|
+
<h3 class="mt-2 text-sm font-semibold text-gray-900">No <%= @resource_class.title.downcase %></h3>
|
130
|
+
<p class="mt-1 text-sm text-gray-500">Get started by creating a new <%= @resource_class.singular_title.downcase %>.</p>
|
131
|
+
<div class="mt-6">
|
132
|
+
<%= link_to easy_admin.new_resource_path(@resource_class.route_key),
|
133
|
+
class: "inline-flex items-center rounded-md bg-blue-600 px-3 py-2 text-sm font-semibold text-white shadow-sm hover:bg-blue-500 focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-blue-600" do %>
|
134
|
+
<svg class="-ml-0.5 mr-1.5 h-5 w-5" viewBox="0 0 20 20" fill="currentColor">
|
135
|
+
<path d="M10.75 4.75a.75.75 0 00-1.5 0v4.5h-4.5a.75.75 0 000 1.5h4.5v4.5a.75.75 0 001.5 0v-4.5h4.5a.75.75 0 000-1.5h-4.5v-4.5z"/>
|
136
|
+
</svg>
|
137
|
+
New <%= @resource_class.singular_title %>
|
138
|
+
<% end %>
|
139
|
+
</div>
|
140
|
+
</div>
|
141
|
+
<% end %>
|
142
|
+
</turbo-frame>
|