lesli 5.0.19 → 5.0.20
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/stylesheets/lesli/application.css +1 -0
- data/app/helpers/lesli/navigation_helper.rb +6 -0
- data/app/interfaces/lesli/responder_interface.rb +35 -19
- data/app/models/concerns/account_initializer.rb +2 -3
- data/app/models/concerns/user_security.rb +5 -4
- data/app/models/lesli/role/action.rb +3 -2
- data/app/models/lesli/shared/dashboard.rb +2 -2
- data/app/models/lesli/user/session.rb +1 -1
- data/app/operators/lesli/role_operator.rb +9 -4
- data/app/services/lesli/role/action_service.rb +2 -3
- data/app/views/lesli/abouts/welcome.html.erb +8 -5
- data/app/views/lesli/apps/show.html.erb +21 -33
- data/app/views/lesli/errors/not_found.html.erb +32 -0
- data/app/views/lesli/errors/unauthorized.html.erb +48 -0
- data/app/views/lesli/layouts/application-lesli.html.erb +1 -2
- data/app/views/lesli/partials/_application-analytics.html.erb +2 -2
- data/app/views/lesli/partials/_application-lesli-header.html.erb +60 -65
- data/app/views/lesli/partials/_application-lesli-navigation.html.erb +23 -5
- data/config/importmap.rb +0 -10
- data/config/initializers/devise_rails_8_patch.rb +8 -0
- data/config/initializers/lesli.rb +27 -23
- data/db/migrate/v1/0000120310_create_lesli_role_privileges.rb +2 -2
- data/db/seed/users.rb +5 -3
- data/lib/lesli/engine.rb +0 -14
- data/lib/lesli/routing.rb +1 -1
- data/lib/lesli/version.rb +2 -2
- data/lib/rspec/testers/request.rb +15 -6
- data/lib/scss/_apps.scss +93 -0
- data/lib/scss/application.scss +34 -0
- data/lib/tasks/lesli/db.rake +1 -1
- data/lib/tasks/lesli_tasks.rake +3 -0
- data/readme.md +9 -10
- metadata +28 -8
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 126a19d2153659244f65bb4a49db4618786defe3328e86f2d7217bea1fb66ffb
|
4
|
+
data.tar.gz: 89b09d6eec6bb3e320c2eb09e07ae50011d047cf12668479c1565a117954506f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7c51533de90a1b6ac70ed9d41f5b329fbbbb35660a348f1ce37aebf1cd29ead7ccaf94e5884c6389c1939c7e62a8b72a48317322b2c010f57a2bbb6a9f98cb3c
|
7
|
+
data.tar.gz: b1aec4ddf728cdd79d7a44ec0b2d5836773cf53d31ed09ceecbb068daeeadba185d6661063aaa1769a1beaf12748b21236ecbede30f032f268b8750cddf6a417
|
@@ -0,0 +1 @@
|
|
1
|
+
body.lesli.apps.show .lesli-element-header{margin-bottom:5rem !important}body.lesli.apps.show .engines{gap:24px;margin-inline-end:auto;margin-inline-start:auto}body.lesli.apps.show .engines a{flex-basis:318px;text-align:center;padding:2rem .4rem 2.8rem;border:#fff 1px solid;border-radius:6px;background-color:#fff;transition:all ease-in-out .2s;box-shadow:rgba(9,30,66,.25) 0px 4px 8px -2px,rgba(9,30,66,.08) 0px 0px 0px 1px}body.lesli.apps.show .engines a:hover{border-color:var(--lesli-color-primary);transform:translateY(-2px)}body.lesli.apps.show .engines a.is-active{background-color:#f0f4ff;border-color:var(--lesli-color-primary)}body.lesli.apps.show .engines a svg{margin-right:.4rem;fill:var(--lesli-color-primary)}body.lesli.apps.show .engines a p{font-size:14}body.lesli.apps.show .engines a span{font-weight:600;font-size:20px}body.lesli.apps.show .engines a span,body.lesli.apps.show .engines a p{color:var(--lesli-color-primary)}
|
@@ -33,6 +33,12 @@ Building a better future, one line of code at a time.
|
|
33
33
|
module Lesli
|
34
34
|
module NavigationHelper
|
35
35
|
|
36
|
+
def navigation_partial
|
37
|
+
engine = lesli_engine[:code]
|
38
|
+
path = engine == "root" ? "partials/navigation" : "#{engine}/partials/navigation"
|
39
|
+
lookup_context.exists?(path, [], true) ? path : nil
|
40
|
+
end
|
41
|
+
|
36
42
|
# Prints a separator line
|
37
43
|
def navigation_separator
|
38
44
|
content_tag(:li) do
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Lesli
|
4
4
|
|
5
|
-
Copyright (c)
|
5
|
+
Copyright (c) 2025, Lesli Technologies, S. A.
|
6
6
|
|
7
7
|
This program is free software: you can redistribute it and/or modify
|
8
8
|
it under the terms of the GNU General Public License as published by
|
@@ -17,17 +17,17 @@ GNU General Public License for more details.
|
|
17
17
|
You should have received a copy of the GNU General Public License
|
18
18
|
along with this program. If not, see http://www.gnu.org/licenses/.
|
19
19
|
|
20
|
-
Lesli ·
|
20
|
+
Lesli · Ruby on Rails SaaS Development Framework.
|
21
21
|
|
22
|
-
Made with ♥ by
|
22
|
+
Made with ♥ by LesliTech
|
23
23
|
Building a better future, one line of code at a time.
|
24
24
|
|
25
25
|
@contact hello@lesli.tech
|
26
|
-
@website https://lesli.tech
|
26
|
+
@website https://www.lesli.tech
|
27
27
|
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
28
28
|
|
29
|
-
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
30
|
-
// ·
|
29
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
30
|
+
// ·
|
31
31
|
=end
|
32
32
|
|
33
33
|
module Lesli
|
@@ -72,27 +72,43 @@ module Lesli
|
|
72
72
|
end
|
73
73
|
|
74
74
|
# JSON not found response
|
75
|
-
def respond_with_not_found
|
76
|
-
|
77
|
-
|
78
|
-
|
75
|
+
def respond_with_not_found message=nil
|
76
|
+
|
77
|
+
@message = message || I18n.t("core.shared.messages_danger_not_found")
|
78
|
+
respond_to do |format|
|
79
|
+
format.json{ respond_with_http(404, { message: @message }) }
|
80
|
+
format.html{ render('lesli/errors/not_found', status: :not_found) }
|
81
|
+
end
|
79
82
|
end
|
80
83
|
|
81
84
|
# JSON not found response
|
82
85
|
def respond_with_unauthorized(detail = {})
|
83
|
-
error_object = {}
|
84
86
|
|
85
|
-
error_object
|
86
|
-
|
87
|
+
@error_object = {
|
88
|
+
error_role: nil,
|
89
|
+
error_detail: nil,
|
90
|
+
error_message: I18n.t("core.shared.view_text_unauthorized_request")
|
91
|
+
}
|
87
92
|
|
88
|
-
|
93
|
+
unless Rails.env.production?
|
94
|
+
@error_object[:error_detail] = detail unless detail.empty?
|
95
|
+
if current_user.present?
|
96
|
+
@error_object[:error_role] = "( #{current_user.lesliroles.map(&:name).join(', ')} )"
|
97
|
+
end
|
98
|
+
end
|
89
99
|
|
90
100
|
respond_to do |format|
|
91
|
-
format.json
|
92
|
-
format.html
|
93
|
-
|
94
|
-
# format.xlsx
|
95
|
-
#
|
101
|
+
format.json{ render(status: :unauthorized, json: @error_object) }
|
102
|
+
format.html{ render('lesli/errors/unauthorized', status: :unauthorized) }
|
103
|
+
|
104
|
+
# format.xlsx do
|
105
|
+
# if Rails.env.production?
|
106
|
+
# redirect_to "/401" # Or a specific Excel error download if applicable
|
107
|
+
# else
|
108
|
+
# # For development, you might still want a JSON response for debugging
|
109
|
+
# render status: :unauthorized, json: error_object.to_json
|
110
|
+
# end
|
111
|
+
# end
|
96
112
|
end
|
97
113
|
end
|
98
114
|
|
@@ -58,8 +58,7 @@ module AccountInitializer
|
|
58
58
|
# Add base privileges to roles
|
59
59
|
Lesli::RoleOperator.new(owner).add_owner_actions
|
60
60
|
Lesli::RoleOperator.new(admin).add_owner_actions
|
61
|
-
Lesli::RoleOperator.new(limited).
|
62
|
-
|
61
|
+
Lesli::RoleOperator.new(limited).add_profile_actions
|
63
62
|
|
64
63
|
end
|
65
64
|
|
@@ -69,7 +68,7 @@ module AccountInitializer
|
|
69
68
|
|
70
69
|
LesliSystem.engines.each do |engine, data|
|
71
70
|
|
72
|
-
next if ["Lesli", "LesliBabel", "
|
71
|
+
next if ["Lesli", "LesliBabel", "Root"].include?(engine)
|
73
72
|
|
74
73
|
# Skip if the engine is not defined
|
75
74
|
next unless Object.const_defined?(engine)
|
@@ -73,10 +73,11 @@ module UserSecurity
|
|
73
73
|
# current_user.has_privileges?(controllers, actions)
|
74
74
|
def has_privileges_for?(controller, action)
|
75
75
|
begin
|
76
|
-
return
|
77
|
-
|
78
|
-
|
79
|
-
|
76
|
+
return self.privileges.where(
|
77
|
+
controller: controller,
|
78
|
+
action: action,
|
79
|
+
active: true
|
80
|
+
).exists?
|
80
81
|
rescue => exception
|
81
82
|
return false
|
82
83
|
end
|
@@ -34,14 +34,15 @@ module Lesli
|
|
34
34
|
class Role::Action < ApplicationLesliRecord
|
35
35
|
belongs_to :role
|
36
36
|
|
37
|
-
|
37
|
+
after_create :synchronize_privileges
|
38
|
+
after_update :synchronize_privileges
|
38
39
|
after_destroy :synchronize_privileges
|
39
40
|
|
40
41
|
belongs_to :action, class_name: "SystemController::Action"
|
41
42
|
belongs_to :system_controller_action, class_name: "SystemController::Action", foreign_key: "action_id"
|
42
43
|
|
43
44
|
def synchronize_privileges
|
44
|
-
Lesli::RoleOperator.new(self).synchronize
|
45
|
+
Lesli::RoleOperator.new(self.role, self).synchronize
|
45
46
|
end
|
46
47
|
|
47
48
|
def self.index current_user, query, role
|
@@ -34,13 +34,13 @@ module Lesli
|
|
34
34
|
module Shared
|
35
35
|
class DashboardFallback < ::Lesli::ApplicationLesliRecord
|
36
36
|
self.abstract_class = true
|
37
|
-
def self.
|
37
|
+
def self.initialize_account(account)
|
38
38
|
end
|
39
39
|
end
|
40
40
|
|
41
41
|
base_class = "::LesliDashboard::Shared::Dashboard".safe_constantize || DashboardFallback
|
42
42
|
|
43
|
-
class Dashboard <
|
43
|
+
class Dashboard < base_class
|
44
44
|
self.abstract_class = true
|
45
45
|
end
|
46
46
|
end
|
@@ -34,12 +34,14 @@ module Lesli
|
|
34
34
|
class RoleOperator < Lesli::ApplicationLesliService
|
35
35
|
|
36
36
|
@role = nil
|
37
|
+
@action = nil
|
37
38
|
|
38
|
-
def initialize role
|
39
|
+
def initialize role, action=nil
|
39
40
|
@role = role
|
41
|
+
@action = action
|
40
42
|
end
|
41
43
|
|
42
|
-
def
|
44
|
+
def add_profile_actions
|
43
45
|
|
44
46
|
# Adding default system actions for profile descriptor
|
45
47
|
[
|
@@ -100,12 +102,15 @@ module Lesli
|
|
100
102
|
lesli_role_actions.role_id as role_id,
|
101
103
|
lesli_system_controllers.route as controller,
|
102
104
|
lesli_system_controller_actions.name as action,
|
103
|
-
|
105
|
+
lesli_role_actions.deleted_at IS NULL as active
|
104
106
|
)).with_deleted
|
105
107
|
|
106
108
|
|
107
109
|
# get privileges only for the given role, this is needed to sync only modified roles
|
108
|
-
records = records.where("lesli_role_actions.role_id" => @role)
|
110
|
+
records = records.where("lesli_role_actions.role_id" => @role.id)
|
111
|
+
|
112
|
+
# get privileges only for the given role action, this is needed to sync only modified actions
|
113
|
+
records = records.where("lesli_role_actions.id" => @action.id) if @action
|
109
114
|
|
110
115
|
|
111
116
|
# we use the deleted_at column to know if a privilege is enable or disable, NULL values
|
@@ -6,7 +6,7 @@ module Lesli
|
|
6
6
|
super(Lesli::Role::Action.with_deleted.find(id))
|
7
7
|
end
|
8
8
|
|
9
|
-
def index
|
9
|
+
def index role_id
|
10
10
|
|
11
11
|
def clean action
|
12
12
|
{
|
@@ -21,6 +21,7 @@ module Lesli
|
|
21
21
|
role_actions = {}
|
22
22
|
|
23
23
|
Lesli::Role::Action.with_deleted.joins(system_controller_action: :system_controller)
|
24
|
+
.where(:role_id => role_id)
|
24
25
|
.select(
|
25
26
|
:id,
|
26
27
|
:role_id,
|
@@ -68,8 +69,6 @@ module Lesli
|
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
|
-
|
72
|
-
|
73
72
|
role_actions
|
74
73
|
end
|
75
74
|
end
|
@@ -20,9 +20,9 @@ html, body, * {
|
|
20
20
|
background-color: #ffffff;
|
21
21
|
background-position: 0 0,55px 55px;
|
22
22
|
background-image:
|
23
|
-
radial-gradient(#0d52bf
|
24
|
-
radial-gradient(#0d52bf
|
25
|
-
animation: rotateBackground
|
23
|
+
radial-gradient(#0d52bf 1px, transparent 2px),
|
24
|
+
radial-gradient(#0d52bf 1px, #ffffff 2px);
|
25
|
+
animation: rotateBackground 10s linear infinite;
|
26
26
|
}
|
27
27
|
|
28
28
|
.page-welcome svg {
|
@@ -118,15 +118,18 @@ html, body, * {
|
|
118
118
|
The Open Source Ruby on Rails <span>SaaS Development Framework</span>
|
119
119
|
</h1>
|
120
120
|
<div class="buttons">
|
121
|
-
<a class="doc" target="blank" href="https://www.lesli.dev/">
|
121
|
+
<a class="doc" target="blank" href="https://www.lesli.dev/lesli/">
|
122
122
|
Documentation
|
123
123
|
</a>
|
124
124
|
<a class="start" target="blank" href="https://www.lesli.dev/start/">
|
125
125
|
Getting started
|
126
126
|
</a>
|
127
127
|
</div>
|
128
|
-
|
128
|
+
<% unless defined?(LesliShield) %>
|
129
|
+
<%= link_to("Apps", "/lesli/apps") unless defined?(LesliDashboard) %>
|
130
|
+
<% end %>
|
129
131
|
<% if defined?(LesliShield) %>
|
132
|
+
<%= link_to("Apps", "/lesli/apps") if user_signed_in? && !defined?(LesliDashboard) %>
|
130
133
|
<%= link_to("Dashboard", "/dashboard") if user_signed_in? && defined?(LesliDashboard) %>
|
131
134
|
<%= link_to("Logout", "/logout") if user_signed_in? %>
|
132
135
|
<%= link_to("Login", "/login") unless user_signed_in? %>
|
@@ -9,40 +9,28 @@ document.addEventListener('turbo:load', () => {
|
|
9
9
|
})
|
10
10
|
})
|
11
11
|
</script>
|
12
|
-
|
13
|
-
|
14
|
-
|
12
|
+
<%
|
13
|
+
@navigation_engines = [
|
14
|
+
:dashboard,
|
15
|
+
:admin,
|
16
|
+
:mailer,
|
17
|
+
:bell,
|
18
|
+
:calendar,
|
19
|
+
:papers,
|
20
|
+
:support,
|
21
|
+
:shield,
|
22
|
+
:security,
|
23
|
+
:audit,
|
24
|
+
:babel
|
25
|
+
]
|
26
|
+
%>
|
27
|
+
|
28
|
+
<%= render(LesliView::Layout::Container.new("lesli-apps", dashboard: false)) do %>
|
15
29
|
<%= render("lesli_dashboard/dashboards/shared/header") if defined?(LesliDashboard) %>
|
16
30
|
|
17
|
-
<section
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
<%# 01. Administration %>
|
22
|
-
<%= navigation_engine_admin %>
|
23
|
-
|
24
|
-
<%# 02. Sales & Marketing %>
|
25
|
-
<%= navigation_engine_mailer %>
|
26
|
-
|
27
|
-
<%# 03. Productivity & Teamwork%>
|
28
|
-
<%= navigation_engine_calendar %>
|
29
|
-
<%= navigation_engine_dashboard %>
|
30
|
-
<%= navigation_engine_bell %>
|
31
|
-
<%= navigation_engine_papers %>
|
32
|
-
|
33
|
-
<%# 05. Analytics %>
|
34
|
-
<%= navigation_engine_audit %>
|
35
|
-
|
36
|
-
<%# 07. IT & Help Desk %>
|
37
|
-
<%= navigation_engine_support %>
|
38
|
-
|
39
|
-
<%# 08. Security & Privacy %>
|
40
|
-
<%= navigation_engine_shield %>
|
41
|
-
<%= navigation_engine_security %>
|
42
|
-
|
43
|
-
<%# 09. Integrations %>
|
44
|
-
<%= navigation_engine_babel %>
|
45
|
-
</div>
|
46
|
-
</div>
|
31
|
+
<section class="columns is-multiline is-mobile is-centered engines">
|
32
|
+
<% @navigation_engines.each do |engine| %>
|
33
|
+
<%= public_send("navigation_engine_#{engine}") %>
|
34
|
+
<% end %>
|
47
35
|
</section>
|
48
36
|
<% end %>
|
@@ -0,0 +1,32 @@
|
|
1
|
+
<style>
|
2
|
+
.error-404 .material-symbols {
|
3
|
+
font-size: 8rem;
|
4
|
+
color: rgb(190,190,190);
|
5
|
+
}
|
6
|
+
.error-404 h2 {
|
7
|
+
font-size: 2rem;
|
8
|
+
color: #3d211b;
|
9
|
+
}
|
10
|
+
|
11
|
+
.error-404 p {
|
12
|
+
font-size: 1.4rem;
|
13
|
+
font-weight: 300;
|
14
|
+
}
|
15
|
+
</style>
|
16
|
+
<%= render(LesliView::Layout::Container.new("accounts")) do %>
|
17
|
+
<section class="hero is-medium error-404">
|
18
|
+
<div class="hero-body has-text-centered">
|
19
|
+
|
20
|
+
<div class="mb-6">
|
21
|
+
<%= render(LesliView::Elements::Empty.new(text:nil)) %>
|
22
|
+
</div>
|
23
|
+
|
24
|
+
<h2 class="mb-4">404 Not found</h2>
|
25
|
+
|
26
|
+
<p>
|
27
|
+
<%= @message %>
|
28
|
+
</p>
|
29
|
+
</div>
|
30
|
+
</section>
|
31
|
+
<% end %>
|
32
|
+
|
@@ -0,0 +1,48 @@
|
|
1
|
+
<style>
|
2
|
+
.error-401 .material-symbols {
|
3
|
+
font-size: 8rem;
|
4
|
+
color: rgb(190,190,190);
|
5
|
+
}
|
6
|
+
.error-401 h2 {
|
7
|
+
font-size: 2rem;
|
8
|
+
color: #7a0000;
|
9
|
+
}
|
10
|
+
|
11
|
+
.error-401 p {
|
12
|
+
font-size: 1.4rem;
|
13
|
+
font-weight: 300;
|
14
|
+
}
|
15
|
+
</style>
|
16
|
+
<%= render(LesliView::Layout::Container.new("accounts")) do %>
|
17
|
+
<section class="hero is-medium error-401">
|
18
|
+
<div class="hero-body has-text-centered">
|
19
|
+
|
20
|
+
<div class="mb-6">
|
21
|
+
<span class="icon">
|
22
|
+
<span class="material-symbols">
|
23
|
+
shield_lock
|
24
|
+
</span>
|
25
|
+
</span>
|
26
|
+
</div>
|
27
|
+
|
28
|
+
<h2 class="mb-4">401 Unauthorized</h2>
|
29
|
+
|
30
|
+
<p>
|
31
|
+
We could not validate your credentials.
|
32
|
+
Please ask the administrator to send you an invite to see this content.
|
33
|
+
</p>
|
34
|
+
|
35
|
+
<div class="box mt-6">
|
36
|
+
<ul>
|
37
|
+
<!--li><%= @error_object[:error_message] %></li-->
|
38
|
+
<li>
|
39
|
+
<%= @error_object.dig(:error_detail, :controller) %>
|
40
|
+
(<%= @error_object.dig(:error_detail, :action) %>)
|
41
|
+
</li>
|
42
|
+
<li><%= @error_object[:error_role] %></li>
|
43
|
+
</ul>
|
44
|
+
</div>
|
45
|
+
</div>
|
46
|
+
</section>
|
47
|
+
<% end %>
|
48
|
+
|
@@ -40,14 +40,13 @@ Building a better future, one line of code at a time.
|
|
40
40
|
</head>
|
41
41
|
<body class="<%= application_body_class %>">
|
42
42
|
<%= render(partial: "lesli/partials/application-lesli-header") %>
|
43
|
-
<%= render(partial: "lesli/partials/application-lesli-navigation") %>
|
44
43
|
<%= render(partial: "lesli/partials/application-lesli-notifications") %>
|
45
44
|
<main class="lesli-application-app">
|
46
45
|
<%= render(partial: "lesli/partials/application-lesli-sidebar") %>
|
47
46
|
<%= render(partial: "lesli/partials/application-lesli-content") %>
|
48
47
|
</main>
|
49
48
|
<%= render(partial: "lesli_assets/partials/application-lesli-icons-engines") %>
|
50
|
-
|
49
|
+
<%= render(partial: "lesli/partials/application-analytics") %>
|
51
50
|
<%= yield(:application_lesli_body_bottom) %>
|
52
51
|
</body>
|
53
52
|
</html>
|
@@ -36,14 +36,14 @@ Building a better future, one line of code at a time.
|
|
36
36
|
<% protected_controllers = ["confirmations"] %>
|
37
37
|
|
38
38
|
<% # Get an specific site tracking id or use the development default %>
|
39
|
-
<% tracking_id = Rails.application.credentials.dig(:providers, :
|
39
|
+
<% tracking_id = Rails.application.credentials.dig(:providers, :google, :tag_manager) || ENV["PROVIDERS_GOOGLE_TAG_MANAGER"] %>
|
40
40
|
|
41
41
|
<% # check if analytics is enabled in the settings file %>
|
42
42
|
<% enable_analytics = Lesli.config.security[:enable_analytics] %>
|
43
43
|
|
44
44
|
<% if Rails.env.production? && enable_analytics && tracking_id %>
|
45
45
|
|
46
|
-
<%
|
46
|
+
<% unless protected_controllers.include?(controller_name) %>
|
47
47
|
|
48
48
|
<!-- Google tag (gtag.js) -->
|
49
49
|
<script async src="https://www.googletagmanager.com/gtag/js?id=<%= tracking_id %>"></script>
|
@@ -30,23 +30,16 @@ Building a better future, one line of code at a time.
|
|
30
30
|
// ·
|
31
31
|
%>
|
32
32
|
|
33
|
-
<%#
|
34
|
-
<%
|
33
|
+
<%# Get the navigation partial for every engine %>
|
34
|
+
<% engine_navigation_partial = navigation_partial %>
|
35
35
|
|
36
|
-
<%# validate the path to be sure the partial exists when trying to render it %>
|
37
|
-
<% custom_navigation_exists = lookup_context.exists?(custom_navigation_path, nil, true) %>
|
38
|
-
|
39
|
-
<%# render navigation partial %>
|
40
|
-
<% if custom_navigation_exists %>
|
41
|
-
|
42
|
-
<%= render partial: custom_navigation_path %>
|
43
|
-
|
44
|
-
<% else %>
|
45
36
|
<header class="lesli-application-header">
|
46
|
-
<
|
47
|
-
<
|
37
|
+
<div class="container" x-data="{ navActive: false }">
|
38
|
+
<nav class="navbar" role="navigation" aria-label="main navigation">
|
48
39
|
<div class="navbar-brand">
|
49
|
-
<a
|
40
|
+
<a
|
41
|
+
class="navbar-item p-0"
|
42
|
+
href="<%= defined?(LesliDashboard) ? '/dashboard' : '/' %>">
|
50
43
|
<%= customization_instance_logo_tag(logo: "app-logo", options: { alt: "Lesli app logo" }) %>
|
51
44
|
</a>
|
52
45
|
<a
|
@@ -62,68 +55,70 @@ Building a better future, one line of code at a time.
|
|
62
55
|
<span aria-hidden="true"></span>
|
63
56
|
</a>
|
64
57
|
</div>
|
65
|
-
<div class="navbar-menu"
|
66
|
-
|
67
|
-
<div class="navbar-start">
|
68
|
-
</div>
|
69
|
-
<div class="navbar-end">
|
58
|
+
<div class="navbar-menu" :class="{ 'is-active': navActive }">
|
59
|
+
<div class="navbar-end is-flex is-justify-content-center">
|
70
60
|
|
61
|
+
<!-- tickets -->
|
71
62
|
<div class="navbar-item">
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
</span>
|
81
|
-
<span class="count" v-if="storeLayout.header.support > 0">
|
82
|
-
</span>
|
83
|
-
</a>
|
84
|
-
<% end %>
|
85
|
-
|
86
|
-
<!-- tickets -->
|
87
|
-
<% if defined?(LesliSupport) %>
|
88
|
-
<%= link_to(
|
89
|
-
lesli_support.tickets_path,
|
90
|
-
:class => "header-indicator",
|
91
|
-
:data => { turbo_frame: '_top' }) do %>
|
92
|
-
<span class="ri-ticket-2-line"></span>
|
93
|
-
<% if @lesli[:tickets] > 0 %>
|
94
|
-
<span class="count"></span>
|
95
|
-
<% end %>
|
96
|
-
<% end %>
|
63
|
+
<% if defined?(LesliSupport) %>
|
64
|
+
<%= link_to(
|
65
|
+
lesli_support.tickets_path,
|
66
|
+
:class => "header-indicator",
|
67
|
+
:data => { turbo_frame: '_top' }) do %>
|
68
|
+
<span class="ri-ticket-2-line"></span>
|
69
|
+
<% if @lesli[:tickets] > 0 %>
|
70
|
+
<span class="count"></span>
|
97
71
|
<% end %>
|
72
|
+
<% end %>
|
73
|
+
<% end %>
|
74
|
+
</div>
|
98
75
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
<% end %>
|
76
|
+
<!-- notifications -->
|
77
|
+
<div class="navbar-item">
|
78
|
+
<% if defined?(LesliBell) %>
|
79
|
+
<%= link_to(
|
80
|
+
lesli_bell.notifications_path,
|
81
|
+
:class => "header-indicator",
|
82
|
+
:data => { turbo_frame: '_top' }) do %>
|
83
|
+
<% if @lesli[:notifications] > 0 %>
|
84
|
+
<span class="ri-notification-3-fill has-text-primary"></span>
|
85
|
+
<% else %>
|
86
|
+
<span class="ri-notification-3-line"></span>
|
111
87
|
<% end %>
|
88
|
+
<% end %>
|
89
|
+
<% end %>
|
90
|
+
</div>
|
112
91
|
|
113
|
-
|
114
|
-
|
92
|
+
<!-- app selector -->
|
93
|
+
<div class="navbar-item">
|
94
|
+
<%= navigation_link(lesli.apps_path, nil, "ri-apps-2-line") %>
|
95
|
+
</div>
|
115
96
|
|
116
|
-
|
117
|
-
|
97
|
+
<!-- user profile -->
|
98
|
+
<div class="navbar-item">
|
99
|
+
<%= navigation_link(lesli.apps_path, nil, "ri-user-smile-line") %>
|
100
|
+
</div>
|
118
101
|
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
</div>
|
102
|
+
<!-- logout from session -->
|
103
|
+
<div class="navbar-item">
|
104
|
+
<%= navigation_link(main_app.destroy_user_session_path, nil, "ri-logout-circle-r-line") if defined?(LesliShield) %>
|
123
105
|
</div>
|
124
106
|
</div>
|
107
|
+
<div class="navbar-end is-hidden-desktop">
|
108
|
+
<%= render(engine_navigation_partial) if engine_navigation_partial %>
|
109
|
+
</div>
|
110
|
+
</div>
|
111
|
+
</nav>
|
112
|
+
</div>
|
113
|
+
</header>
|
114
|
+
|
115
|
+
<%# Build the engine navigation %>
|
116
|
+
<% if engine_navigation_partial %>
|
117
|
+
<nav class="navbar lesli-application-navigation is-hidden-touch">
|
118
|
+
<div class="navbar-menu">
|
119
|
+
<div class="navbar-start is-flex-grow-1 is-justify-content-center">
|
120
|
+
<%= render(engine_navigation_partial) %>
|
125
121
|
</div>
|
126
122
|
</div>
|
127
123
|
</nav>
|
128
|
-
</header>
|
129
124
|
<% end %>
|
@@ -48,12 +48,30 @@ Building a better future, one line of code at a time.
|
|
48
48
|
|
49
49
|
<%# render navigation partial %>
|
50
50
|
<% if custom_sidebar_exists %>
|
51
|
-
<nav
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
51
|
+
<nav
|
52
|
+
class="navbar lesli-application-navigation"
|
53
|
+
role="navigation"
|
54
|
+
aria-label="main navigation"
|
55
|
+
x-data="{ navActive: false }">
|
56
|
+
<div class="navbar-brand">
|
57
|
+
<a
|
58
|
+
class="navbar-burger"
|
59
|
+
role="button"
|
60
|
+
aria-label="menu"
|
61
|
+
aria-expanded="false"
|
62
|
+
@click="navActive = !navActive"
|
63
|
+
:class="{ 'is-active': navActive }">
|
64
|
+
<span aria-hidden="true"></span>
|
65
|
+
<span aria-hidden="true"></span>
|
66
|
+
<span aria-hidden="true"></span>
|
67
|
+
<span aria-hidden="true"></span>
|
68
|
+
</a>
|
69
|
+
</div>
|
70
|
+
<div class="navbar-menu" :class="{ 'is-active': navActive }">
|
71
|
+
<div class="navbar-start is-flex-grow-1 is-justify-content-center">
|
72
|
+
<%= render partial: custom_sidebar_path %>
|
56
73
|
</div>
|
74
|
+
</div>
|
57
75
|
</nav>
|
58
76
|
<% else %>
|
59
77
|
<!-- no navigation found -->
|
data/config/importmap.rb
CHANGED
@@ -2,13 +2,3 @@
|
|
2
2
|
|
3
3
|
pin "application", to: "lesli/application.js", preload: true
|
4
4
|
pin "@hotwired/turbo-rails", to: "turbo.min.js"
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
#pin "chart.js", to: "https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js"
|
9
|
-
#pin "chart.js", to: "https://ga.jspm.io/npm:chart.js@4.5.1/dist/chart.esm.js"
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
# my_engine/config/importmap.rb
|
14
|
-
#pin_all_from File.expand_path("../app/assets/javascripts", __dir__)
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Lesli
|
4
4
|
|
5
|
-
Copyright (c)
|
5
|
+
Copyright (c) 2025, Lesli Technologies, S. A.
|
6
6
|
|
7
7
|
This program is free software: you can redistribute it and/or modify
|
8
8
|
it under the terms of the GNU General Public License as published by
|
@@ -19,7 +19,7 @@ along with this program. If not, see http://www.gnu.org/licenses/.
|
|
19
19
|
|
20
20
|
Lesli · Ruby on Rails SaaS Development Framework.
|
21
21
|
|
22
|
-
Made with ♥ by
|
22
|
+
Made with ♥ by LesliTech
|
23
23
|
Building a better future, one line of code at a time.
|
24
24
|
|
25
25
|
@contact hello@lesli.tech
|
@@ -33,7 +33,7 @@ Building a better future, one line of code at a time.
|
|
33
33
|
Lesli.configure do |config|
|
34
34
|
|
35
35
|
|
36
|
-
#
|
36
|
+
# Enable or disable demo mode.
|
37
37
|
config.demo = false
|
38
38
|
|
39
39
|
|
@@ -41,7 +41,7 @@ Lesli.configure do |config|
|
|
41
41
|
config.instance = "Lesli"
|
42
42
|
|
43
43
|
|
44
|
-
#
|
44
|
+
# Provides organization details displayed throughout the system.
|
45
45
|
config.company = {
|
46
46
|
name: "Lesli",
|
47
47
|
email: "hello@lesli.tech",
|
@@ -49,26 +49,26 @@ Lesli.configure do |config|
|
|
49
49
|
}
|
50
50
|
|
51
51
|
|
52
|
-
#
|
52
|
+
# List of supported languages (requires `LesliBabel`).
|
53
53
|
config.locales = {
|
54
54
|
:en => "English", # English
|
55
|
-
:de => "Deutsch",
|
56
|
-
|
57
|
-
|
55
|
+
:de => "Deutsch", # Deutsch/German
|
56
|
+
:pl => "Polski", # Polski/Polish/Poland
|
57
|
+
:nl => "Dutch", # Dutch/Nederlands/Netherlands
|
58
58
|
:es => "Español", # Español/Spanish
|
59
|
-
|
60
|
-
|
61
|
-
:it => "Italiano",
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
59
|
+
:uk => "украї́нська", # украї́нська/Ukrainian
|
60
|
+
:sr => "Српски", # Српски/Srpski/Serbian
|
61
|
+
:it => "Italiano", # Italiano/Italian
|
62
|
+
:hr => "Hrvatski", # Hrvatski/Croatian
|
63
|
+
:fr => "Français", # French
|
64
|
+
:pt => "Português", # Portuguese
|
65
|
+
:tr => "Türkçe", # Turkish
|
66
|
+
:ro => "Română", # Romanian
|
67
|
+
:bg => "български" # Bulgarian
|
68
68
|
}
|
69
69
|
|
70
70
|
|
71
|
-
#
|
71
|
+
# Define time zone, week start day, and custom date/time formats.
|
72
72
|
config.datetime = {
|
73
73
|
:time_zone => "America/Guatemala",
|
74
74
|
:start_week_on => "monday",
|
@@ -84,9 +84,9 @@ Lesli.configure do |config|
|
|
84
84
|
}
|
85
85
|
|
86
86
|
|
87
|
-
#
|
87
|
+
# Customize system-wide security behavior.
|
88
88
|
config.security = {
|
89
|
-
password: "Test123!",
|
89
|
+
password: "Test123!", # Default password for development, test & demo environments
|
90
90
|
enable_debug: false,
|
91
91
|
enable_becoming: false,
|
92
92
|
enable_analytics: true,
|
@@ -97,7 +97,7 @@ Lesli.configure do |config|
|
|
97
97
|
}
|
98
98
|
|
99
99
|
|
100
|
-
#
|
100
|
+
# Customize the color palette and layout.
|
101
101
|
config.theme = {
|
102
102
|
color_primary: "#193d8d",
|
103
103
|
color_sidebar: "#ffffff",
|
@@ -110,15 +110,19 @@ Lesli.configure do |config|
|
|
110
110
|
|
111
111
|
#
|
112
112
|
config.layout = {
|
113
|
-
|
113
|
+
tasks: true,
|
114
|
+
babel: false,
|
115
|
+
profile: true,
|
116
|
+
notifications: true
|
114
117
|
}
|
115
118
|
|
116
119
|
|
117
|
-
#
|
120
|
+
# Specify default paths for email templates.
|
118
121
|
config.mailer = {
|
119
122
|
templates: "lesli_mailer/emails/lesli"
|
120
123
|
}
|
121
124
|
|
125
|
+
# Control redirection paths after login.
|
122
126
|
config.path_after_login = "/"
|
123
127
|
config.path_after_login = "/dashboard" if defined?(LesliDashboard)
|
124
128
|
end
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
Lesli
|
4
4
|
|
5
|
-
Copyright (c)
|
5
|
+
Copyright (c) 2025, Lesli Technologies, S. A.
|
6
6
|
|
7
7
|
This program is free software: you can redistribute it and/or modify
|
8
8
|
it under the terms of the GNU General Public License as published by
|
@@ -19,7 +19,7 @@ along with this program. If not, see http://www.gnu.org/licenses/.
|
|
19
19
|
|
20
20
|
Lesli · Ruby on Rails SaaS Development Framework.
|
21
21
|
|
22
|
-
Made with ♥ by
|
22
|
+
Made with ♥ by LesliTech
|
23
23
|
Building a better future, one line of code at a time.
|
24
24
|
|
25
25
|
@contact hello@lesli.tech
|
data/db/seed/users.rb
CHANGED
@@ -53,12 +53,14 @@ passguest = passowner
|
|
53
53
|
|
54
54
|
|
55
55
|
# build a random password for the owner, admin and guest users
|
56
|
-
# only for production and only when LesliShield is installed
|
57
|
-
if
|
56
|
+
# only for production and only when LesliShield is installed and
|
57
|
+
# only if the "demo mode" is not active in the
|
58
|
+
# config/initializers/lesli.rb file
|
59
|
+
if Rails.env.production? && defined?(LesliShield) && !Lesli.config.demo
|
58
60
|
passowner = LesliShield::Tokens.friendly_token
|
59
61
|
passadmin = LesliShield::Tokens.friendly_token
|
60
62
|
passguest = LesliShield::Tokens.friendly_token
|
61
|
-
end
|
63
|
+
end
|
62
64
|
|
63
65
|
|
64
66
|
# create the owner user for the account,
|
data/lib/lesli/engine.rb
CHANGED
@@ -93,23 +93,9 @@ module Lesli
|
|
93
93
|
# Lesli Framework Mailer configuration
|
94
94
|
|
95
95
|
|
96
|
-
# Development mailer by default
|
97
|
-
config.action_mailer.delivery_method ||= :letter_opener
|
98
|
-
|
99
96
|
# Add the Lesli root folder for email development tempaltes
|
100
97
|
config.action_mailer.preview_paths << root.join("lib", "mailer_previews")
|
101
98
|
|
102
|
-
#
|
103
|
-
config.action_mailer.default_options ||= {
|
104
|
-
|
105
|
-
# Use the main email in the lesli settings as email sender
|
106
|
-
from: Lesli.config.company.dig(:email)
|
107
|
-
}
|
108
|
-
|
109
|
-
# Mailer url options for development
|
110
|
-
config.action_mailer.default_url_options ||= {
|
111
|
-
host: "http://0.0.0.0:3000"
|
112
|
-
}
|
113
99
|
|
114
100
|
# Does not work too well
|
115
101
|
# if Lesli.config.security.dig(:enable_debug)
|
data/lib/lesli/routing.rb
CHANGED
data/lib/lesli/version.rb
CHANGED
@@ -36,12 +36,21 @@ require Lesli::Engine.root.join("lib/rspec/helpers/rails_helper")
|
|
36
36
|
require Lesli::Engine.root.join("lib/rspec/helpers/lesli_helper")
|
37
37
|
require Lesli::Engine.root.join("lib/rspec/helpers/response_request_helper")
|
38
38
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
39
|
+
|
40
|
+
# · Dynamically build a path where the engine is mounted
|
41
|
+
def build_engine_path(engine_name, path)
|
42
|
+
|
43
|
+
# get the engine information
|
44
|
+
engine = LesliSystem.engine(engine_name)
|
45
|
+
|
46
|
+
# return the path if no engine found
|
47
|
+
return path unless engine
|
48
|
+
|
49
|
+
engine_constant = engine[:name].constantize
|
50
|
+
|
51
|
+
# build the path inside the engine mounted path
|
52
|
+
"#{engine_constant::Engine.routes.find_script_name({})}/#{path}"
|
53
|
+
end
|
45
54
|
|
46
55
|
|
47
56
|
# · Authentication context
|
data/lib/scss/_apps.scss
ADDED
@@ -0,0 +1,93 @@
|
|
1
|
+
/*
|
2
|
+
Lesli
|
3
|
+
|
4
|
+
Copyright (c) 2025, Lesli Technologies, S. A.
|
5
|
+
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
7
|
+
it under the terms of the GNU General Public License as published by
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
9
|
+
(at your option) any later version.
|
10
|
+
|
11
|
+
This program is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU General Public License
|
17
|
+
along with this program. If not, see http://www.gnu.org/licenses/.
|
18
|
+
|
19
|
+
Lesli · Ruby on Rails SaaS Development Framework.
|
20
|
+
|
21
|
+
Made with ♥ by LesliTech
|
22
|
+
Building a better future, one line of code at a time.
|
23
|
+
|
24
|
+
@contact hello@lesli.tech
|
25
|
+
@website https://www.lesli.tech
|
26
|
+
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
27
|
+
|
28
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
29
|
+
// ·
|
30
|
+
*/
|
31
|
+
|
32
|
+
|
33
|
+
// ·
|
34
|
+
@use "lesli-css/sass/helpers/shadow";
|
35
|
+
@use "lesli-css/sass/helpers/breakpoint";
|
36
|
+
|
37
|
+
|
38
|
+
// ·
|
39
|
+
body.lesli.apps.show {
|
40
|
+
|
41
|
+
.lesli-element-header {
|
42
|
+
margin-bottom: 5rem !important;
|
43
|
+
}
|
44
|
+
|
45
|
+
.engines {
|
46
|
+
gap: 24px;
|
47
|
+
margin-inline-end: auto;
|
48
|
+
margin-inline-start: auto;
|
49
|
+
|
50
|
+
a {
|
51
|
+
flex-basis: 318px;
|
52
|
+
text-align: center;
|
53
|
+
padding: 2rem .4rem 2.8rem;
|
54
|
+
border: white 1px solid;
|
55
|
+
border-radius: 6px;
|
56
|
+
background-color: white;
|
57
|
+
transition: all ease-in-out .2s;
|
58
|
+
|
59
|
+
@include shadow.lesli-shadow();
|
60
|
+
|
61
|
+
&:hover {
|
62
|
+
border-color: var(--lesli-color-primary);
|
63
|
+
transform: translateY(-2px);
|
64
|
+
}
|
65
|
+
|
66
|
+
&.is-active {
|
67
|
+
background-color: #F0F4FF;
|
68
|
+
border-color: var(--lesli-color-primary);
|
69
|
+
}
|
70
|
+
|
71
|
+
// engine logo
|
72
|
+
svg {
|
73
|
+
margin-right: .4rem;
|
74
|
+
fill: var(--lesli-color-primary);
|
75
|
+
}
|
76
|
+
|
77
|
+
// engine description
|
78
|
+
p {
|
79
|
+
font-size: 14;
|
80
|
+
}
|
81
|
+
|
82
|
+
// engine name
|
83
|
+
span {
|
84
|
+
font-weight: 600;
|
85
|
+
font-size: 20px;
|
86
|
+
}
|
87
|
+
|
88
|
+
span, p {
|
89
|
+
color: var(--lesli-color-primary);
|
90
|
+
}
|
91
|
+
}
|
92
|
+
}
|
93
|
+
}
|
@@ -0,0 +1,34 @@
|
|
1
|
+
/*
|
2
|
+
Lesli
|
3
|
+
|
4
|
+
Copyright (c) 2025, Lesli Technologies, S. A.
|
5
|
+
|
6
|
+
This program is free software: you can redistribute it and/or modify
|
7
|
+
it under the terms of the GNU General Public License as published by
|
8
|
+
the Free Software Foundation, either version 3 of the License, or
|
9
|
+
(at your option) any later version.
|
10
|
+
|
11
|
+
This program is distributed in the hope that it will be useful,
|
12
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
13
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
14
|
+
GNU General Public License for more details.
|
15
|
+
|
16
|
+
You should have received a copy of the GNU General Public License
|
17
|
+
along with this program. If not, see http://www.gnu.org/licenses/.
|
18
|
+
|
19
|
+
Lesli · Ruby on Rails SaaS Development Framework.
|
20
|
+
|
21
|
+
Made with ♥ by LesliTech
|
22
|
+
Building a better future, one line of code at a time.
|
23
|
+
|
24
|
+
@contact hello@lesli.tech
|
25
|
+
@website https://www.lesli.tech
|
26
|
+
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
27
|
+
|
28
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
29
|
+
// ·
|
30
|
+
*/
|
31
|
+
|
32
|
+
|
33
|
+
// ·
|
34
|
+
@use "apps";
|
data/lib/tasks/lesli/db.rake
CHANGED
data/lib/tasks/lesli_tasks.rake
CHANGED
data/readme.md
CHANGED
@@ -73,20 +73,19 @@ bundle add lesli
|
|
73
73
|
```
|
74
74
|
|
75
75
|
```shell
|
76
|
-
#
|
77
|
-
|
78
|
-
|
76
|
+
# Add Lesli to your app
|
77
|
+
rails generate lesli:install
|
78
|
+
```
|
79
|
+
```shell
|
79
80
|
# Setup database for development
|
80
81
|
rake lesli:db:dev
|
81
82
|
```
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
Rails.application.routes.draw do
|
86
|
-
Lesli::Routing.mount
|
87
|
-
end
|
83
|
+
```shell
|
84
|
+
# Start your app
|
85
|
+
rails server
|
88
86
|
```
|
89
87
|
|
88
|
+
|
90
89
|
<br />
|
91
90
|
|
92
91
|
|
@@ -107,7 +106,7 @@ bundle install
|
|
107
106
|
```
|
108
107
|
```shell
|
109
108
|
# Generate Lesli initializer
|
110
|
-
rails
|
109
|
+
rails generate lesli:install
|
111
110
|
```
|
112
111
|
```shell
|
113
112
|
# Hard reset Database for development:
|
metadata
CHANGED
@@ -1,15 +1,29 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lesli
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.0.
|
4
|
+
version: 5.0.20
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- The Lesli Development Team
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-
|
11
|
+
date: 2025-08-01 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: rails
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '8.0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '8.0'
|
13
27
|
- !ruby/object:Gem::Dependency
|
14
28
|
name: i18n-js
|
15
29
|
requirement: !ruby/object:Gem::Requirement
|
@@ -28,16 +42,16 @@ dependencies:
|
|
28
42
|
name: importmap-rails
|
29
43
|
requirement: !ruby/object:Gem::Requirement
|
30
44
|
requirements:
|
31
|
-
- - "
|
45
|
+
- - "~>"
|
32
46
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
47
|
+
version: 2.2.0
|
34
48
|
type: :runtime
|
35
49
|
prerelease: false
|
36
50
|
version_requirements: !ruby/object:Gem::Requirement
|
37
51
|
requirements:
|
38
|
-
- - "
|
52
|
+
- - "~>"
|
39
53
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
54
|
+
version: 2.2.0
|
41
55
|
- !ruby/object:Gem::Dependency
|
42
56
|
name: turbo-rails
|
43
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,7 +178,8 @@ dependencies:
|
|
164
178
|
- - "~>"
|
165
179
|
- !ruby/object:Gem::Version
|
166
180
|
version: '0.6'
|
167
|
-
description:
|
181
|
+
description: Lesli is a SaaS development framework designed to build highly scalable,
|
182
|
+
secure and customizable software products.
|
168
183
|
email:
|
169
184
|
- hello@lesli.tech
|
170
185
|
executables: []
|
@@ -248,6 +263,8 @@ files:
|
|
248
263
|
- app/views/lesli/abouts/welcome.html.erb
|
249
264
|
- app/views/lesli/apps/show.html.erb
|
250
265
|
- app/views/lesli/emails/user_mailer/invitation.html.erb
|
266
|
+
- app/views/lesli/errors/not_found.html.erb
|
267
|
+
- app/views/lesli/errors/unauthorized.html.erb
|
251
268
|
- app/views/lesli/layouts/application-devise.html.erb
|
252
269
|
- app/views/lesli/layouts/application-lesli.html.erb
|
253
270
|
- app/views/lesli/layouts/application-public.html.erb
|
@@ -276,6 +293,7 @@ files:
|
|
276
293
|
- app/views/lesli/wrappers/_application-devise.html.erb
|
277
294
|
- config/importmap.rb
|
278
295
|
- config/initializers/devise.rb
|
296
|
+
- config/initializers/devise_rails_8_patch.rb
|
279
297
|
- config/initializers/lesli.rb
|
280
298
|
- config/initializers/lesli_migration_helpers.rb
|
281
299
|
- config/locales/devise.en.yml
|
@@ -362,6 +380,8 @@ files:
|
|
362
380
|
- lib/rspec/testers/controller.rb
|
363
381
|
- lib/rspec/testers/model.rb
|
364
382
|
- lib/rspec/testers/request.rb
|
383
|
+
- lib/scss/_apps.scss
|
384
|
+
- lib/scss/application.scss
|
365
385
|
- lib/tasks/lesli/controllers.rake
|
366
386
|
- lib/tasks/lesli/db.rake
|
367
387
|
- lib/tasks/lesli/dev.rake
|
@@ -389,7 +409,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
389
409
|
requirements:
|
390
410
|
- - ">="
|
391
411
|
- !ruby/object:Gem::Version
|
392
|
-
version: '2
|
412
|
+
version: '3.2'
|
393
413
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
394
414
|
requirements:
|
395
415
|
- - ">="
|