easy-admin-rails 0.2.5 → 0.2.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/builds/easy_admin.base.js +95 -0
- data/app/assets/builds/easy_admin.base.js.map +3 -3
- data/app/assets/builds/easy_admin.css +226 -0
- data/app/components/easy_admin/fields/form/belongs_to_component.rb +0 -1
- data/app/components/easy_admin/form_layout_component.rb +553 -0
- data/app/components/easy_admin/navbar_component.rb +19 -4
- data/app/components/easy_admin/permissions/user_role_permissions_component.rb +1 -3
- data/app/components/easy_admin/profile/change_password_modal_component.rb +75 -0
- data/app/components/easy_admin/profile/profile_tab_component.rb +92 -0
- data/app/components/easy_admin/profile/security_tab_component.rb +53 -0
- data/app/components/easy_admin/profile/settings_component.rb +103 -0
- data/app/components/easy_admin/show_layout_component.rb +694 -24
- data/app/components/easy_admin/two_factor/backup_codes_component.rb +118 -0
- data/app/components/easy_admin/two_factor/setup_component.rb +124 -0
- data/app/components/easy_admin/two_factor/status_component.rb +92 -0
- data/app/controllers/concerns/easy_admin/two_factor.rb +110 -0
- data/app/controllers/easy_admin/application_controller.rb +10 -5
- data/app/controllers/easy_admin/batch_actions_controller.rb +0 -1
- data/app/controllers/easy_admin/concerns/inline_field_editing.rb +4 -11
- data/app/controllers/easy_admin/concerns/resource_loading.rb +10 -9
- data/app/controllers/easy_admin/concerns/resource_pagination.rb +3 -0
- data/app/controllers/easy_admin/dashboards_controller.rb +0 -1
- data/app/controllers/easy_admin/profile_controller.rb +25 -0
- data/app/controllers/easy_admin/resources_controller.rb +1 -5
- data/app/controllers/easy_admin/row_actions_controller.rb +1 -4
- data/app/controllers/easy_admin/sessions_controller.rb +107 -1
- data/app/helpers/easy_admin/fields_helper.rb +8 -22
- data/app/javascript/easy_admin/controllers/infinite_scroll_controller.js +12 -0
- data/app/javascript/easy_admin/controllers/vertical_tabs_controller.js +112 -0
- data/app/javascript/easy_admin/controllers.js +3 -1
- data/app/models/easy_admin/admin_user.rb +3 -0
- data/app/views/easy_admin/profile/backup_codes_regenerated.turbo_stream.erb +12 -0
- data/app/views/easy_admin/profile/change_password.html.erb +24 -0
- data/app/views/easy_admin/profile/index.html.erb +1 -0
- data/app/views/easy_admin/profile/password_error.turbo_stream.erb +6 -0
- data/app/views/easy_admin/profile/password_invalid_current.turbo_stream.erb +6 -0
- data/app/views/easy_admin/profile/password_updated.turbo_stream.erb +9 -0
- data/app/views/easy_admin/profile/two_factor_backup_codes.html.erb +24 -0
- data/app/views/easy_admin/profile/two_factor_enabled.turbo_stream.erb +12 -0
- data/app/views/easy_admin/profile/two_factor_invalid_code.turbo_stream.erb +6 -0
- data/app/views/easy_admin/profile/two_factor_not_enabled.turbo_stream.erb +6 -0
- data/app/views/easy_admin/profile/two_factor_setup.html.erb +24 -0
- data/app/views/easy_admin/profile/two_factor_unavailable.turbo_stream.erb +6 -0
- data/app/views/easy_admin/resources/edit.html.erb +2 -2
- data/app/views/easy_admin/resources/new.html.erb +2 -2
- data/app/views/easy_admin/resources/show.html.erb +3 -1
- data/app/views/easy_admin/sessions/two_factor_verification.html.erb +48 -0
- data/app/views/easy_admin/sessions/verify_2fa_error.turbo_stream.erb +13 -0
- data/config/routes.rb +20 -1
- data/lib/easy-admin-rails.rb +1 -0
- data/lib/easy_admin/field.rb +3 -2
- data/lib/easy_admin/layouts/builders/base_layout_builder.rb +245 -0
- data/lib/easy_admin/layouts/builders/form_layout_builder.rb +208 -0
- data/lib/easy_admin/layouts/builders/index_layout_builder.rb +22 -0
- data/lib/easy_admin/layouts/builders/show_layout_builder.rb +199 -0
- data/lib/easy_admin/layouts/dsl.rb +200 -0
- data/lib/easy_admin/layouts/layout_context.rb +189 -0
- data/lib/easy_admin/layouts/nodes/base_node.rb +88 -0
- data/lib/easy_admin/layouts/nodes/divider.rb +27 -0
- data/lib/easy_admin/layouts/nodes/field_node.rb +57 -0
- data/lib/easy_admin/layouts/nodes/grid.rb +60 -0
- data/lib/easy_admin/layouts/nodes/render_node.rb +41 -0
- data/lib/easy_admin/layouts/nodes/root.rb +25 -0
- data/lib/easy_admin/layouts/nodes/section.rb +46 -0
- data/lib/easy_admin/layouts/nodes/spacer.rb +17 -0
- data/lib/easy_admin/layouts/nodes/stubs.rb +109 -0
- data/lib/easy_admin/layouts/nodes/tab.rb +40 -0
- data/lib/easy_admin/layouts/nodes/tabs.rb +40 -0
- data/lib/easy_admin/layouts.rb +28 -0
- data/lib/easy_admin/permissions/resource_permissions.rb +1 -5
- data/lib/easy_admin/resource/base.rb +2 -2
- data/lib/easy_admin/resource/dsl.rb +2 -11
- data/lib/easy_admin/resource/field_registry.rb +58 -2
- data/lib/easy_admin/resource.rb +0 -9
- data/lib/easy_admin/resource_modules.rb +21 -4
- data/lib/easy_admin/two_factor_authentication.rb +156 -0
- data/lib/easy_admin/version.rb +1 -1
- data/lib/generators/easy_admin/permissions/install_generator.rb +0 -10
- data/lib/generators/easy_admin/permissions/templates/migrations/create_permission_tables.rb +33 -3
- data/lib/generators/easy_admin/two_factor/templates/README +29 -0
- data/lib/generators/easy_admin/two_factor/templates/migration.rb +10 -0
- data/lib/generators/easy_admin/two_factor/two_factor_generator.rb +22 -0
- metadata +49 -9
- data/lib/easy_admin/resource/form_builder.rb +0 -123
- data/lib/easy_admin/resource/layout_builder.rb +0 -249
- data/lib/easy_admin/resource/show_builder.rb +0 -359
- data/lib/generators/easy_admin/permissions/templates/migrations/update_users_for_permissions.rb +0 -6
- data/lib/generators/easy_admin/rbac/rbac_generator.rb +0 -244
- data/lib/generators/easy_admin/rbac/templates/add_rbac_to_admin_users.rb +0 -23
- data/lib/generators/easy_admin/rbac/templates/super_admin.rb +0 -34
@@ -0,0 +1,92 @@
|
|
1
|
+
module EasyAdmin
|
2
|
+
module Profile
|
3
|
+
class ProfileTabComponent < BaseComponent
|
4
|
+
def initialize(user:)
|
5
|
+
@user = user
|
6
|
+
end
|
7
|
+
|
8
|
+
def view_template
|
9
|
+
div do
|
10
|
+
# Section header
|
11
|
+
div(class: "mb-6") do
|
12
|
+
h2(class: "text-lg font-medium text-gray-900") { "Profile Information" }
|
13
|
+
p(class: "text-sm text-gray-600 mt-1") { "Update your personal information" }
|
14
|
+
end
|
15
|
+
|
16
|
+
# Profile form
|
17
|
+
form(action: EasyAdmin::Engine.routes.url_helpers.update_profile_path, method: :patch) do
|
18
|
+
# Rails CSRF token
|
19
|
+
input(type: "hidden", name: "authenticity_token", value: helpers.form_authenticity_token) if helpers.respond_to?(:form_authenticity_token)
|
20
|
+
# Rails method spoofing for PATCH
|
21
|
+
input(type: "hidden", name: "_method", value: "patch")
|
22
|
+
|
23
|
+
div(class: "space-y-6") do
|
24
|
+
# First Name
|
25
|
+
div do
|
26
|
+
label(for: "admin_user_first_name", class: "block text-sm font-medium text-gray-700 mb-2") { "First Name" }
|
27
|
+
input(
|
28
|
+
type: "text",
|
29
|
+
name: "admin_user[first_name]",
|
30
|
+
id: "admin_user_first_name",
|
31
|
+
value: @user.first_name,
|
32
|
+
class: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
|
33
|
+
placeholder: "Enter your first name"
|
34
|
+
)
|
35
|
+
render_field_errors(@user, :first_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
# Last Name
|
39
|
+
div do
|
40
|
+
label(for: "admin_user_last_name", class: "block text-sm font-medium text-gray-700 mb-2") { "Last Name" }
|
41
|
+
input(
|
42
|
+
type: "text",
|
43
|
+
name: "admin_user[last_name]",
|
44
|
+
id: "admin_user_last_name",
|
45
|
+
value: @user.last_name,
|
46
|
+
class: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
|
47
|
+
placeholder: "Enter your last name"
|
48
|
+
)
|
49
|
+
render_field_errors(@user, :last_name)
|
50
|
+
end
|
51
|
+
|
52
|
+
# Email
|
53
|
+
div do
|
54
|
+
label(for: "admin_user_email", class: "block text-sm font-medium text-gray-700 mb-2") { "Email" }
|
55
|
+
input(
|
56
|
+
type: "email",
|
57
|
+
name: "admin_user[email]",
|
58
|
+
id: "admin_user_email",
|
59
|
+
value: @user.email,
|
60
|
+
class: "w-full px-3 py-2 border border-gray-300 rounded-md focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500",
|
61
|
+
placeholder: "Enter your email address"
|
62
|
+
)
|
63
|
+
render_field_errors(@user, :email)
|
64
|
+
end
|
65
|
+
|
66
|
+
# Submit button
|
67
|
+
div do
|
68
|
+
input(
|
69
|
+
type: "submit",
|
70
|
+
value: "Update Profile",
|
71
|
+
class: "bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-blue-500 focus:ring-offset-2 transition-colors cursor-pointer"
|
72
|
+
)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
private
|
80
|
+
|
81
|
+
def render_field_errors(object, field)
|
82
|
+
return unless object.errors[field].any?
|
83
|
+
|
84
|
+
div(class: "mt-1") do
|
85
|
+
object.errors[field].each do |error|
|
86
|
+
p(class: "text-sm text-red-600") { error }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module EasyAdmin
|
2
|
+
module Profile
|
3
|
+
class SecurityTabComponent < BaseComponent
|
4
|
+
def initialize(user:)
|
5
|
+
@user = user
|
6
|
+
end
|
7
|
+
|
8
|
+
def view_template
|
9
|
+
div(class: "space-y-8") do
|
10
|
+
# Password section
|
11
|
+
render_password_section
|
12
|
+
|
13
|
+
# Two-factor authentication section
|
14
|
+
div(id: "two_factor_section") do
|
15
|
+
render_two_factor_section
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def render_password_section
|
23
|
+
div do
|
24
|
+
# Section header
|
25
|
+
div(class: "mb-6") do
|
26
|
+
h2(class: "text-lg font-medium text-gray-900") { "Change Password" }
|
27
|
+
p(class: "text-sm text-gray-600 mt-1") { "Update your password to keep your account secure" }
|
28
|
+
end
|
29
|
+
|
30
|
+
# Change password button
|
31
|
+
a(
|
32
|
+
href: EasyAdmin::Engine.routes.url_helpers.change_password_path,
|
33
|
+
class: "bg-blue-600 text-white px-4 py-2 rounded-md hover:bg-blue-700 transition-colors",
|
34
|
+
data: { turbo_frame: "modal" }
|
35
|
+
) { "Change Password" }
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def render_two_factor_section
|
40
|
+
div(class: "pt-8 border-t border-gray-200") do
|
41
|
+
# Section header
|
42
|
+
div(class: "mb-6") do
|
43
|
+
h2(class: "text-lg font-medium text-gray-900") { "Two-Factor Authentication" }
|
44
|
+
p(class: "text-sm text-gray-600 mt-1") { "Add an extra layer of security to your account" }
|
45
|
+
end
|
46
|
+
|
47
|
+
# 2FA status and actions
|
48
|
+
render EasyAdmin::TwoFactor::StatusComponent.new(user: @user)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
module EasyAdmin
|
2
|
+
module Profile
|
3
|
+
class SettingsComponent < BaseComponent
|
4
|
+
def initialize(user:)
|
5
|
+
@user = user
|
6
|
+
end
|
7
|
+
|
8
|
+
def view_template
|
9
|
+
div(class: "min-h-screen bg-gray-50 py-6") do
|
10
|
+
div(class: "max-w-6xl mx-auto px-6") do
|
11
|
+
# Page header
|
12
|
+
div(class: "mb-8") do
|
13
|
+
h1(class: "text-2xl font-semibold text-gray-900") { "Settings" }
|
14
|
+
p(class: "text-gray-600 mt-1") { "Manage your account settings and preferences" }
|
15
|
+
end
|
16
|
+
|
17
|
+
# Settings layout with vertical tabs
|
18
|
+
div(
|
19
|
+
class: "bg-white rounded-lg overflow-hidden",
|
20
|
+
data: { controller: "vertical-tabs" }
|
21
|
+
) do
|
22
|
+
div(class: "flex") do
|
23
|
+
# Left sidebar - Tab navigation
|
24
|
+
render_tab_navigation
|
25
|
+
|
26
|
+
# Right content area
|
27
|
+
render_content_area
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def render_tab_navigation
|
37
|
+
nav(class: "w-64 bg-gray-50 border-r border-gray-200 py-6") do
|
38
|
+
div(class: "px-4") do
|
39
|
+
render_tab_item("profile", "Profile", profile_icon, active: true)
|
40
|
+
render_tab_item("security", "Security", security_icon)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def render_tab_item(tab_id, label, icon_svg, active: false)
|
46
|
+
button(
|
47
|
+
class: "w-full flex items-center px-3 py-2 mb-2 text-left rounded-lg transition-colors #{tab_classes(active)}",
|
48
|
+
data: {
|
49
|
+
action: "click->vertical-tabs#switchTab",
|
50
|
+
vertical_tabs_target: "tab",
|
51
|
+
tab_id: tab_id
|
52
|
+
}
|
53
|
+
) do
|
54
|
+
div(class: "w-5 h-5 mr-3") { unsafe_raw(icon_svg) }
|
55
|
+
span(class: "font-medium") { label }
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def render_content_area
|
60
|
+
div(class: "flex-1 p-6") do
|
61
|
+
# Profile tab content
|
62
|
+
div(
|
63
|
+
class: "tab-content",
|
64
|
+
data: {
|
65
|
+
vertical_tabs_target: "content",
|
66
|
+
tab_id: "profile"
|
67
|
+
}
|
68
|
+
) do
|
69
|
+
render EasyAdmin::Profile::ProfileTabComponent.new(user: @user)
|
70
|
+
end
|
71
|
+
|
72
|
+
# Security tab content
|
73
|
+
div(
|
74
|
+
class: "tab-content hidden",
|
75
|
+
data: {
|
76
|
+
vertical_tabs_target: "content",
|
77
|
+
tab_id: "security"
|
78
|
+
}
|
79
|
+
) do
|
80
|
+
render EasyAdmin::Profile::SecurityTabComponent.new(user: @user)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def tab_classes(active)
|
86
|
+
if active
|
87
|
+
"bg-blue-50 text-blue-700 border-blue-200"
|
88
|
+
else
|
89
|
+
"text-gray-700 hover:bg-gray-100 hover:text-gray-900"
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
# SVG Icons
|
94
|
+
def profile_icon
|
95
|
+
'<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M16 7a4 4 0 11-8 0 4 4 0 018 0zM12 14a7 7 0 00-7 7h14a7 7 0 00-7-7z"/></svg>'
|
96
|
+
end
|
97
|
+
|
98
|
+
def security_icon
|
99
|
+
'<svg fill="none" stroke="currentColor" viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 15v2m-6 4h12a2 2 0 002-2v-6a2 2 0 00-2-2H6a2 2 0 00-2 2v6a2 2 0 002 2zm10-10V7a4 4 0 00-8 0v4h8z"/></svg>'
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|