lesli 5.0.21 → 5.0.23
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/Rakefile +4 -0
- data/app/assets/config/lesli_manifest.js +2 -2
- data/app/assets/images/lesli/brand/register-background.jpg +0 -0
- data/app/assets/stylesheets/lesli/application.css +192 -1
- data/app/controllers/lesli/abouts_controller.rb +12 -13
- data/app/controllers/lesli/application_controller.rb +1 -42
- data/app/controllers/lesli/application_lesli_controller.rb +8 -1
- data/app/controllers/lesli/apps_controller.rb +25 -0
- data/app/controllers/lesli/items/actions_controller.rb +122 -0
- data/app/{models/lesli/item/activity.rb → controllers/lesli/items/activities_controller.rb} +2 -2
- data/app/controllers/lesli/items/discussions_controller.rb +93 -0
- data/app/controllers/lesli/{system_controllers_controller.rb → resources_controller.rb} +3 -3
- data/app/controllers/lesli/shared/dashboards_controller.rb +11 -279
- data/app/helpers/lesli/customization_helper.rb +3 -3
- data/app/helpers/lesli/html_helper.rb +114 -2
- data/app/helpers/lesli/navigation_helper.rb +8 -25
- data/app/helpers/lesli/system_helper.rb +21 -4
- data/app/helpers/lesli/turbo_helper.rb +19 -2
- data/app/interfaces/lesli/requester_interface.rb +2 -29
- data/app/interfaces/lesli/responder_interface.rb +121 -61
- data/app/models/concerns/lesli/account_initializer.rb +13 -13
- data/{lib/rspec/factories/lesli_account.rb → app/models/concerns/lesli/account_logs.rb} +23 -9
- data/app/models/concerns/lesli/user_extensions.rb +33 -51
- data/app/models/lesli/account.rb +6 -5
- data/app/models/lesli/application_lesli_record.rb +14 -0
- data/app/models/lesli/items/action.rb +15 -0
- data/app/models/lesli/items/activity.rb +50 -0
- data/app/models/lesli/items/discussion.rb +15 -0
- data/app/models/lesli/{user/journal.rb → resource.rb} +9 -4
- data/app/models/lesli/role.rb +2 -17
- data/app/models/lesli/shared/dashboard.rb +1 -0
- data/app/models/lesli/user.rb +23 -77
- data/app/services/lesli/application_lesli_service.rb +21 -4
- data/app/{operators/lesli/controller_operator.rb → services/lesli/resource_service.rb} +92 -23
- data/app/services/lesli/role_service.rb +16 -10
- data/app/services/lesli/user_service.rb +28 -27
- data/app/views/lesli/abouts/welcome.html.erb +11 -11
- data/app/views/lesli/apps/show.html.erb +1 -1
- data/app/views/lesli/errors/not_found.html.erb +1 -1
- data/app/views/lesli/errors/unauthorized.html.erb +9 -11
- data/app/views/lesli/layouts/application-devise.html.erb +6 -9
- data/app/views/lesli/layouts/application-lesli.html.erb +9 -9
- data/app/views/lesli/layouts/application-public.html.erb +4 -18
- data/app/views/lesli/layouts/mailer.html.erb +1 -1
- data/app/views/lesli/partials/{_application-analytics.html.erb → _application-lesli-analytics.html.erb} +18 -9
- data/app/views/lesli/partials/{_application-lesli-scss.html.erb → _application-lesli-assets.html.erb} +9 -11
- data/{db/migrate/v1/0000110310_create_lesli_account_settings.rb → app/views/lesli/partials/_application-lesli-data.html.erb} +11 -7
- data/app/views/lesli/partials/{_application-head.html.erb → _application-lesli-head.html.erb} +2 -2
- data/app/views/lesli/partials/_application-lesli-header.html.erb +6 -6
- data/app/views/lesli/partials/_application-lesli-navigation.html.erb +3 -6
- data/app/views/lesli/partials/_application-lesli-notifications.html.erb +0 -1
- data/app/views/lesli/partials/turbo/_redirection.html.erb +5 -0
- data/app/views/lesli/{partials/_application-data.html.erb → shared/dashboards/edit.html.erb} +2 -6
- data/app/views/lesli/shared/dashboards/{_show.html.erb → show.html.erb} +3 -3
- data/config/brakeman.yml +55 -0
- data/config/importmap.rb +0 -3
- data/config/initializers/devise.rb +1 -2
- data/config/initializers/lesli.rb +27 -14
- data/config/initializers/lesli_migration_helpers.rb +0 -5
- data/config/locales/translations.en.yml +6 -2
- data/config/locales/translations.es.yml +5 -2
- data/config/locales/translations.fr.yml +1 -4
- data/config/locales/translations.it.yml +5 -2
- data/config/locales/translations.pt.yml +1 -4
- data/config/routes.rb +4 -6
- data/db/migrate/v1/{0000000310_create_lesli_users.rb → 0000000210_create_lesli_users.rb} +4 -0
- data/db/migrate/v1/{0000000210_create_lesli_roles.rb → 0000000310_create_lesli_roles.rb} +6 -0
- data/db/migrate/v1/{0000100110_create_lesli_system_controllers.rb → 0000000410_create_lesli_resources.rb} +8 -5
- data/db/seed/users.rb +1 -1
- data/db/seed/xyz.rb +3 -1
- data/lib/generators/lesli/spec/spec_generator.rb +0 -3
- data/lib/generators/lesli/view/view_generator.rb +0 -3
- data/lib/lesli/configuration.rb +1 -1
- data/{app/lib → lib}/lesli/courier.rb +40 -7
- data/lib/lesli/engine.rb +4 -5
- data/lib/lesli/{routing.rb → router.rb} +3 -2
- data/lib/lesli/version.rb +2 -2
- data/lib/lesli.rb +3 -2
- data/lib/migrate/common.rb +2 -0
- data/lib/migrate/items/action_structure.rb +2 -1
- data/lib/migrate/items/activity_structure.rb +12 -2
- data/lib/migrate/items/discussion_structure.rb +1 -1
- data/lib/scss/_apps.scss +1 -0
- data/lib/tasks/lesli/db.rake +5 -5
- data/lib/tasks/lesli/{controllers.rake → resources.rake} +4 -4
- data/lib/tasks/lesli_tasks.rake +13 -3
- data/lib/test/config.rb +111 -0
- data/{db/migrate/v1/0000130210_create_lesli_user_roles.rb → lib/test/helpers/response_integration_helper.rb} +12 -9
- data/{db/migrate/v1/0000100210_create_lesli_system_controller_actions.rb → lib/test/lesli.rb} +28 -9
- data/readme.md +61 -68
- metadata +49 -121
- data/app/helpers/lesli/assets_helper.rb +0 -110
- data/app/helpers/lesli/general_helper.rb +0 -96
- data/app/mailers/lesli/devise_mailer.rb +0 -67
- data/app/models/concerns/lesli/has_activities.rb +0 -29
- data/app/models/concerns/lesli/user_activities.rb +0 -163
- data/app/models/concerns/lesli/user_security.rb +0 -220
- data/app/models/lesli/account/detail.rb +0 -37
- data/app/models/lesli/account/log.rb +0 -57
- data/app/models/lesli/account/request.rb +0 -37
- data/app/models/lesli/descriptor/privilege.rb +0 -39
- data/app/models/lesli/descriptor.rb +0 -57
- data/app/models/lesli/role/action.rb +0 -73
- data/app/models/lesli/role/privilege.rb +0 -38
- data/app/models/lesli/system_controller/action.rb +0 -37
- data/app/models/lesli/system_controller.rb +0 -104
- data/app/models/lesli/user/activity.rb +0 -5
- data/app/models/lesli/user/detail.rb +0 -55
- data/app/models/lesli/user/request.rb +0 -38
- data/app/models/lesli/user/role.rb +0 -39
- data/app/models/lesli/user/session.rb +0 -79
- data/app/models/lesli/user/setting.rb +0 -46
- data/app/operators/lesli/role_operator.rb +0 -153
- data/app/services/lesli/role/action_service.rb +0 -75
- data/app/services/lesli/user/session_service.rb +0 -78
- data/app/validators/lesli/application_lesli_validator.rb +0 -67
- data/app/validators/lesli/users_validator.rb +0 -217
- data/app/views/lesli/emails/user_mailer/invitation.html.erb +0 -23
- data/app/views/lesli/partials/_application-lesli-annoouncements.html.erb +0 -49
- data/app/views/lesli/partials/_application-lesli-chatbox.html.erb +0 -35
- data/app/views/lesli/partials/_application-lesli-javascript.html.erb +0 -48
- data/app/views/lesli/partials/_application-lesli-panels.html.erb +0 -58
- data/app/views/lesli/partials/_application-public-footer.html.erb +0 -51
- data/app/views/lesli/partials/_application-public-javascript.html.erb +0 -49
- data/app/views/lesli/partials/_application-public-scss.html.erb +0 -35
- data/app/views/lesli/shared/dashboards/_edit.html.erb +0 -33
- data/app/views/lesli/wrappers/_application-devise-simple.erb +0 -59
- data/app/views/lesli/wrappers/_application-devise.html.erb +0 -76
- data/config/initializers/devise_rails_8_patch.rb +0 -8
- data/db/migrate/v1/0000110210_create_lesli_account_details.rb +0 -70
- data/db/migrate/v1/0000110410_create_lesli_account_activities.rb +0 -37
- data/db/migrate/v1/0000120210_create_lesli_role_actions.rb +0 -45
- data/db/migrate/v1/0000120310_create_lesli_role_privileges.rb +0 -45
- data/db/migrate/v1/0000130310_create_lesli_user_sessions.rb +0 -56
- data/db/migrate/v1/0000130410_create_lesli_user_activities.rb +0 -37
- data/db/migrate2/0000100510_create_lesli_account_locations.rb +0 -64
- data/db/migrate2/0000100610_create_lesli_account_currencies.rb +0 -48
- data/lib/assets/javascripts/lesli/i18n_js +0 -1095
- data/lib/migrate/shared/dashboard_structure.rb +0 -54
- data/lib/migrate/shared/setting_structure.rb +0 -20
- data/lib/rspec/config/spec_coverage.rb +0 -95
- data/lib/rspec/factories/lesli_role.rb +0 -62
- data/lib/rspec/factories/lesli_user.rb +0 -64
- data/lib/rspec/fixtures/files/lesli-icon.png +0 -0
- data/lib/rspec/fixtures/files/test_file_1.docx +0 -0
- data/lib/rspec/helpers/lesli_helper.rb +0 -54
- data/lib/rspec/helpers/rails_helper.rb +0 -134
- data/lib/rspec/helpers/response_request_helper.rb +0 -214
- data/lib/rspec/helpers/response_service_helper.rb +0 -66
- data/lib/rspec/helpers/spec_helper.rb +0 -99
- data/lib/rspec/lesli_api_tester.rb +0 -133
- data/lib/rspec/lesli_service_tester.rb +0 -46
- data/lib/rspec/testers/controller.rb +0 -63
- data/lib/rspec/testers/model.rb +0 -36
- data/lib/rspec/testers/request.rb +0 -93
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
5
|
-
Copyright (c)
|
|
5
|
+
Copyright (c) 2026, 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
|
|
@@ -29,288 +29,20 @@ Building a better future, one line of code at a time.
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
30
|
// ·
|
|
31
31
|
=end
|
|
32
|
+
|
|
32
33
|
module Lesli
|
|
33
34
|
module Shared
|
|
34
|
-
class DashboardsController < ApplicationLesliController
|
|
35
|
-
#before_action :set_dashboard, only: [:show, :update, :destroy, :options]
|
|
36
|
-
|
|
37
|
-
def edit
|
|
38
|
-
end
|
|
39
|
-
|
|
40
|
-
def show
|
|
41
|
-
builder = LesliSystem::Klass.new(self)
|
|
42
|
-
@dashboard = builder.model.dashboard.first
|
|
43
|
-
end
|
|
44
|
-
|
|
45
|
-
# def index
|
|
46
|
-
# respond_to do |format|
|
|
47
|
-
# format.html {}
|
|
48
|
-
# format.json do
|
|
49
|
-
# dynamic_info = self.class.dynamic_info
|
|
50
|
-
# model = dynamic_info[:model]
|
|
51
|
-
|
|
52
|
-
# dashboards = model.list(current_user, @query)
|
|
53
|
-
# respond_with_successful(dashboards)
|
|
54
|
-
# end
|
|
55
|
-
# end
|
|
56
|
-
# end
|
|
57
|
-
|
|
58
|
-
# def show
|
|
59
|
-
# respond_to do |format|
|
|
60
|
-
# format.html {}
|
|
61
|
-
# format.json do
|
|
62
|
-
# return respond_with_not_found unless @dashboard
|
|
63
|
-
# respond_with_successful(@dashboard.show)
|
|
64
|
-
# end
|
|
65
|
-
# end
|
|
66
|
-
# end
|
|
67
|
-
|
|
68
|
-
# def new
|
|
69
|
-
# end
|
|
70
|
-
|
|
71
|
-
# def edit
|
|
72
|
-
# end
|
|
73
|
-
|
|
74
|
-
# # @controller_action_param :name [String] The name of the new dashboard
|
|
75
|
-
# # @controller_action_param :default [Boolean] A flag that marks this dashboard as default or not. The default dashboard is the dashboard all users will have access to on the root page
|
|
76
|
-
# # @controller_action_param :main [Boolean] A flag that marks this dashboard as main. Since a user can have multiple dashboards, this is the one they will see on the root page when loging in
|
|
77
|
-
# # @controller_action_param :roles_id [Integer] The id of the role that will have access to this dashboard
|
|
78
|
-
# # @controller_action_param :user_main_id [Integer] The id of the user
|
|
79
|
-
# # @controller_action_param :component_attributes [Array] Array of hashes that represent the attributes of the dashboard components
|
|
80
|
-
# # @controller_action_param :component_attributes.name [String] The name of this component given to the user
|
|
81
|
-
# # @controller_action_param :component_attributes.component_id [String] An enum value, that indicates which component is being loaded
|
|
82
|
-
# # @controller_action_param :component_attributes.layout [Integer] Number from 1 to 12, bigger numbers default to 12, smallest numbers default to 1. The column size that the UI component will use
|
|
83
|
-
# # @controller_action_param :component_attributes.index [Integer] The position of the component in the layout
|
|
84
|
-
# # @controller_action_param :component_attributes.configuration [Hash] Specific filtering and configuration of the components
|
|
85
|
-
# # @return [Json] Json that contains wheter the creation of the dashboard was successful or not.
|
|
86
|
-
# # If it is not successful, it returns an error message
|
|
87
|
-
# # @description Creates a new dashboard associated to the *current_user*'s *account*
|
|
88
|
-
# # @example
|
|
89
|
-
# # # Executing this controller's action from javascript's frontend
|
|
90
|
-
# # let data = {
|
|
91
|
-
# # dashboard: {
|
|
92
|
-
# # name: "Sales Dashboard",
|
|
93
|
-
# # default: false,
|
|
94
|
-
# # roles_id: 3,
|
|
95
|
-
# # components_attributes: [
|
|
96
|
-
# # {
|
|
97
|
-
# # name: 'Projects Count',
|
|
98
|
-
# # component_id: projects_component,
|
|
99
|
-
# # layout: 4,
|
|
100
|
-
# # index: 3,
|
|
101
|
-
# # configuration: {}
|
|
102
|
-
# # }, {
|
|
103
|
-
# # name: 'New Customers Count',
|
|
104
|
-
# # component_id: new_customers_component,
|
|
105
|
-
# # layout: 4,
|
|
106
|
-
# # index: 3,
|
|
107
|
-
# # configuration: {}
|
|
108
|
-
# # }
|
|
109
|
-
# # ]
|
|
110
|
-
# # }
|
|
111
|
-
# # };
|
|
112
|
-
# # this.http.post('127.0.0.1/help/dashboards', data);
|
|
113
|
-
# def create
|
|
114
|
-
# dynamic_info = self.class.dynamic_info
|
|
115
|
-
# module_name = dynamic_info[:module_name]
|
|
116
|
-
# model = dynamic_info[:model]
|
|
117
|
-
# full_module_name = dynamic_info[:full_module_name].underscore
|
|
118
|
-
|
|
119
|
-
# dashboard = model.new(dashboard_params)
|
|
120
|
-
# dashboard["#{full_module_name}_account_id".to_sym] = current_user.account.id
|
|
121
|
-
# dashboard.user_creator = current_user
|
|
122
|
-
|
|
123
|
-
# if dashboard.save
|
|
124
|
-
# respond_with_successful(dashboard)
|
|
125
|
-
# else
|
|
126
|
-
# respond_with_error(dashboard.errors.full_messages.to_sentence)
|
|
127
|
-
# end
|
|
128
|
-
# end
|
|
129
|
-
|
|
130
|
-
# # @controller_action_param :name [String] The name of the new dashboard
|
|
131
|
-
# # @controller_action_param :default [Boolean] A flag that marks this dashboard as default or not. The default dashboard is the dashboard all users will have access to on the root page
|
|
132
|
-
# # @controller_action_param :main [Boolean] A flag that marks this dashboard as main. Since a user can have multiple dashboards, this is the one they will see on the root page when loging in
|
|
133
|
-
# # @controller_action_param :roles_id [Integer] The id of the role that will have access to this dashboard
|
|
134
|
-
# # @controller_action_param :user_main_id [Integer] The id of the user
|
|
135
|
-
# # @controller_action_param :component_attributes [Array] Array of hashes that represent the attributes of the dashboard components
|
|
136
|
-
# # @controller_action_param :component_attributes.name [String] The name of this component given to the user
|
|
137
|
-
# # @controller_action_param :component_attributes.component_id [String] An enum value, that indicates which component is being loaded
|
|
138
|
-
# # @controller_action_param :component_attributes.layout [Integer] Number from 1 to 12, bigger numbers default to 12, smallest numbers default to 1. The column size that the UI component will use
|
|
139
|
-
# # @controller_action_param :component_attributes.index [Integer] The position of the component in the layout
|
|
140
|
-
# # @controller_action_param :component_attributes.configuration [Hash] Specific filtering and configuration of the components
|
|
141
|
-
# # @return [Json] Json that contains wheter the dashboard was successfully updated or not.
|
|
142
|
-
# # If it it not successful, it returns an error message
|
|
143
|
-
# # @description Updates an existing dashboard associated to the *current_user*'s *account*.
|
|
144
|
-
# # @example
|
|
145
|
-
# # # Executing this controller's action from javascript's frontend
|
|
146
|
-
# # let dashboard_id = 4;
|
|
147
|
-
# # let data = {
|
|
148
|
-
# # dashboard: {
|
|
149
|
-
# # name: "Sales Dashboard",
|
|
150
|
-
# # default: false,
|
|
151
|
-
# # roles_id: 3,
|
|
152
|
-
# # components_attributes: [
|
|
153
|
-
# # {
|
|
154
|
-
# # name: 'Projects Count',
|
|
155
|
-
# # component_id: projects_component,
|
|
156
|
-
# # layout: 4,
|
|
157
|
-
# # index: 3,
|
|
158
|
-
# # configuration: {}
|
|
159
|
-
# # }, {
|
|
160
|
-
# # name: 'New Customers Count',
|
|
161
|
-
# # component_id: new_customers_component,
|
|
162
|
-
# # layout: 4,
|
|
163
|
-
# # index: 3,
|
|
164
|
-
# # configuration: {}
|
|
165
|
-
# # }
|
|
166
|
-
# # ]
|
|
167
|
-
# # }
|
|
168
|
-
# # };
|
|
169
|
-
# # this.http.put(`127.0.0.1/help/dashboards/${dashboard_id}`, data);
|
|
170
|
-
# def update
|
|
171
|
-
# return respond_with_not_found unless @dashboard
|
|
172
|
-
|
|
173
|
-
# if @dashboard.update(dashboard_params)
|
|
174
|
-
# respond_with_successful(@dashboard.show)
|
|
175
|
-
# else
|
|
176
|
-
# respond_with_error(@dashboard.errors.full_messages.to_sentence)
|
|
177
|
-
# end
|
|
178
|
-
# end
|
|
179
|
-
|
|
180
|
-
# # @return [Json] Json that contains wheter the dashboard was successfully deleted or not.
|
|
181
|
-
# # If it it not successful, it returns an error message
|
|
182
|
-
# # @description Deletes an existing *dashboard* associated to the *current_user*'s *account*.
|
|
183
|
-
# # Since the dashboard has details, these are also deleted. However, if there
|
|
184
|
-
# # is an existing *cloud_object* associated to the *dashboard*, it cannot be deleted
|
|
185
|
-
# # @example
|
|
186
|
-
# # # Executing this controller's action from javascript's frontend
|
|
187
|
-
# # let dashboard_id = 4;
|
|
188
|
-
# # this.http.delete(`127.0.0.1/help/dashboards/${dashboard_id}`);
|
|
189
|
-
# def destroy
|
|
190
|
-
# return respond_with_not_found unless @dashboard
|
|
191
|
-
|
|
192
|
-
# if @dashboard.destroy
|
|
193
|
-
# respond_with_successful
|
|
194
|
-
# else
|
|
195
|
-
# respond_with_error(@dashboard.errors.full_messages.to_sentence)
|
|
196
|
-
# end
|
|
197
|
-
# end
|
|
198
35
|
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
# model = dynamic_info[:module_model]
|
|
36
|
+
# Try to create an instance of the main controller from the engine
|
|
37
|
+
DASH = "::LesliDashboard::Shared::DashboardsController".safe_constantize
|
|
202
38
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
# def resource_component
|
|
207
|
-
# dynamic_info = self.class.dynamic_info
|
|
208
|
-
# component_model = dynamic_info[:component_model]
|
|
209
|
-
|
|
210
|
-
# component_id = sanitize(params[:component_id].to_sym)
|
|
211
|
-
|
|
212
|
-
# # We verify if the method exists, and if it is in the available component list
|
|
213
|
-
# if component_model.respond_to?(component_id) && component_model.component_ids[component_id]
|
|
214
|
-
# respond_with_successful(component_model.public_send(component_id, current_user, @query))
|
|
215
|
-
# else
|
|
216
|
-
# respond_with_not_found()
|
|
217
|
-
# end
|
|
218
|
-
# end
|
|
219
|
-
|
|
220
|
-
# private
|
|
221
|
-
|
|
222
|
-
# # @return [void]
|
|
223
|
-
# # @description Sets the variable @dashboard. The variable contains the *cloud_object* *dashboard*
|
|
224
|
-
# # to be handled by the controller action that called this method
|
|
225
|
-
# # @example
|
|
226
|
-
# # #suppose params[:id] = 1
|
|
227
|
-
# # puts @dashboard # will display nil
|
|
228
|
-
# # set_dashboard
|
|
229
|
-
# # puts @dashboard # will display an instance of CloudHelp:TicketDashboard
|
|
230
|
-
# def set_dashboard
|
|
231
|
-
# dynamic_info = self.class.dynamic_info
|
|
232
|
-
|
|
233
|
-
# model = dynamic_info[:module_model]
|
|
234
|
-
# module_name = dynamic_info[:module_name]
|
|
235
|
-
# module_name_full = dynamic_info[:module_name_full].underscore
|
|
236
|
-
|
|
237
|
-
# # When params[:id] is 'default' order of priority is:
|
|
238
|
-
# # Main dashboard for user goes first
|
|
239
|
-
# # Main dashboard for role goes second
|
|
240
|
-
# # Default dashboard goes third
|
|
241
|
-
# if params[:id] == "default"
|
|
242
|
-
# # Main dashboard for user
|
|
243
|
-
# @dashboard = model.find_by(
|
|
244
|
-
# #"#{full_module_name}_account_id".to_sym => current_user.account.id,
|
|
245
|
-
# account_id: current_user.account.id,
|
|
246
|
-
# main: true,
|
|
247
|
-
# #user_main_id: current_user.id
|
|
248
|
-
# )
|
|
249
|
-
|
|
250
|
-
# return if @dashboard
|
|
251
|
-
|
|
252
|
-
# # Main dashboard for role
|
|
253
|
-
# # @dashboard = model.find_by(
|
|
254
|
-
# # :account_id => current_user.account.id,
|
|
255
|
-
# # role_id: current_user.roles.first.id
|
|
256
|
-
# # )
|
|
257
|
-
# # return if @dashboard
|
|
258
|
-
|
|
259
|
-
# # Default dashboard
|
|
260
|
-
# @dashboard = model.find_by(
|
|
261
|
-
# account_id: current_user.account.id,
|
|
262
|
-
# default: true
|
|
263
|
-
# )
|
|
264
|
-
# else
|
|
265
|
-
# @dashboard = model.find_by(
|
|
266
|
-
# id: params[:id],
|
|
267
|
-
# :account_id => current_user.account.id,
|
|
268
|
-
# )
|
|
269
|
-
# end
|
|
270
|
-
# end
|
|
271
|
-
|
|
272
|
-
# def dashboard_params
|
|
273
|
-
# params.require(:dashboard).permit(
|
|
274
|
-
# :name,
|
|
275
|
-
# :default,
|
|
276
|
-
# :roles_id,
|
|
277
|
-
# components_attributes: [
|
|
278
|
-
# :id,
|
|
279
|
-
# :name,
|
|
280
|
-
# :component_id,
|
|
281
|
-
# :layout,
|
|
282
|
-
# :index,
|
|
283
|
-
# {query_configuration: {}},
|
|
284
|
-
# {custom_configuration: {}},
|
|
285
|
-
# :_destroy
|
|
286
|
-
# ]
|
|
287
|
-
# )
|
|
288
|
-
# end
|
|
289
|
-
|
|
290
|
-
# private
|
|
291
|
-
|
|
292
|
-
# # Build the Rails models and engine information for
|
|
293
|
-
# # the current engine implementing the shared dashboards
|
|
294
|
-
# # Example: For the LesliAudit engine
|
|
295
|
-
# # {
|
|
296
|
-
# # :module_name => "audit",
|
|
297
|
-
# # :module_name_full => "LesliAudit",
|
|
298
|
-
# # :module_model => "LesliAudit::Dashboard",
|
|
299
|
-
# # :module_model_component => "LesliAudit::Dashboard::Component"
|
|
300
|
-
# # }
|
|
301
|
-
# def self.dynamic_info
|
|
302
|
-
|
|
303
|
-
# module_info = self.name.split("::")
|
|
39
|
+
# Create a dummy contoller if the LesliDashboard controller is not installed
|
|
40
|
+
class DashboardsFallbackController < ApplicationLesliController
|
|
41
|
+
end
|
|
304
42
|
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
# module_name: module_name,
|
|
309
|
-
# module_name_full: module_info[0],
|
|
310
|
-
# module_model: "#{ module_info[0] }::Dashboard".constantize,
|
|
311
|
-
# module_model_component: "#{ module_info[0] }::Dashboard::Component".constantize
|
|
312
|
-
# }
|
|
313
|
-
# end
|
|
43
|
+
# Inherit from the available controller from
|
|
44
|
+
# LesliDashboard if installed or use dummy controller to avoid any error
|
|
45
|
+
class DashboardsController < DASH || DashboardsFallbackController
|
|
314
46
|
end
|
|
315
47
|
end
|
|
316
48
|
end
|
|
@@ -48,13 +48,13 @@ module Lesli
|
|
|
48
48
|
logo_path = "#{lesli_instance_code}/brand/#{logo}.svg"
|
|
49
49
|
|
|
50
50
|
# load favicon as PNG for better compatibility between web browsers
|
|
51
|
-
logo_path = "#{lesli_instance_code}/brand/#{logo}.png" if logo == "favicon"
|
|
51
|
+
#logo_path = "#{lesli_instance_code}/brand/#{logo}.png" if logo == "favicon"
|
|
52
52
|
|
|
53
53
|
# loading logo from core, only if builder engine was not installed
|
|
54
|
-
logo_path = "lesli/brand/#{logo}.svg" if lesli_instance_code == "lesli"
|
|
54
|
+
#logo_path = "lesli/brand/#{logo}.svg" if lesli_instance_code == "lesli"
|
|
55
55
|
|
|
56
56
|
# custom logo from settings
|
|
57
|
-
logo_path = @lesli[:customization][:logos][logo.to_sym] if @lesli.dig(:customization, :logos, logo.to_sym)
|
|
57
|
+
#logo_path = @lesli[:customization][:logos][logo.to_sym] if @lesli.dig(:customization, :logos, logo.to_sym)
|
|
58
58
|
|
|
59
59
|
if mode == "pdf"
|
|
60
60
|
wicked_pdf_image_tag(logo_path, options)
|
|
@@ -1,8 +1,120 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
|
|
3
|
+
Lesli
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2026, Lesli Technologies, S. A.
|
|
6
|
+
|
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
This program is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU General Public License
|
|
18
|
+
along with this program. If not, see http://www.gnu.org/licenses/.
|
|
19
|
+
|
|
20
|
+
Lesli · Ruby on Rails SaaS Development Framework.
|
|
21
|
+
|
|
22
|
+
Made with ♥ by LesliTech
|
|
23
|
+
Building a better future, one line of code at a time.
|
|
24
|
+
|
|
25
|
+
@contact hello@lesli.tech
|
|
26
|
+
@website https://www.lesli.tech
|
|
27
|
+
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
|
+
|
|
29
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
+
// ·
|
|
31
|
+
=end
|
|
1
32
|
|
|
2
33
|
module Lesli
|
|
3
34
|
module HtmlHelper
|
|
4
|
-
|
|
5
|
-
|
|
35
|
+
|
|
36
|
+
# Prints link tags to add favicon to websites
|
|
37
|
+
def lesli_favicon
|
|
38
|
+
icon_path = image_url("lesli/brand/favicon.svg")
|
|
39
|
+
safe_join([
|
|
40
|
+
tag.link(href: icon_path, rel: "alternate icon"),
|
|
41
|
+
tag.link(href: icon_path, rel: "icon", type: "image/svg+xml"),
|
|
42
|
+
tag.link(href: icon_path, rel: "mask-icon", color: "#ff8a01")
|
|
43
|
+
])
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# build the text for the html document title
|
|
47
|
+
# this helper works only for rails pages, for vue apps the title must be handled with JS
|
|
48
|
+
def lesli_website_title
|
|
49
|
+
# Use instance variable if set, otherwise construct a dynamic title
|
|
50
|
+
title = @application_html_title || controller_path.delete_prefix("lesli_")
|
|
51
|
+
|
|
52
|
+
# Append action name unless it's "index"
|
|
53
|
+
title += "/#{action_name}" unless action_name == "index"
|
|
54
|
+
|
|
55
|
+
# Append company name if present
|
|
56
|
+
title += " · #{Lesli.config.company.dig(:name)}"
|
|
57
|
+
|
|
58
|
+
title
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
# build description using custom data from controller or engine gem description
|
|
62
|
+
def lesli_website_meta_description
|
|
63
|
+
# if want to get description from gem you can use:
|
|
64
|
+
# Gem::Specification.find_by_name(engine_name).description
|
|
65
|
+
# Gem::Specification.find_by_name(engine_name).summary
|
|
66
|
+
@application_html_description || ""
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# return a string with a css class to identify the body
|
|
70
|
+
# example: builder engine-controller action
|
|
71
|
+
def lesli_application_body_class
|
|
72
|
+
[lesli_instance_code, controller_path.sub("_","-").split("/"), action_name].join(" ")
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
# Return a string path to load the template stylesheet
|
|
76
|
+
# by default we always return the latest version of the template
|
|
77
|
+
#
|
|
78
|
+
# stylesheet from main App
|
|
79
|
+
# lesli_stylesheet_path()
|
|
80
|
+
# /assets/application.css
|
|
81
|
+
#
|
|
82
|
+
# Specific stylesheet from Engine
|
|
83
|
+
# lesli_stylesheet_path(:lesli, 'application')
|
|
84
|
+
# /assets/lesli/application.css
|
|
85
|
+
#
|
|
86
|
+
# Specific stylesheet from gem
|
|
87
|
+
# lesli_stylesheet_path(:lesli_assets, 'templates/application')
|
|
88
|
+
# /assets/lesli_assets/templates/application.css
|
|
89
|
+
def lesli_stylesheet_path(engine = nil, stylesheet = 'application')
|
|
90
|
+
|
|
91
|
+
# Stylesheets from specific engine
|
|
92
|
+
return "#{engine}/#{stylesheet}" if engine.present?
|
|
93
|
+
|
|
94
|
+
# Get current engine information
|
|
95
|
+
engine_code = lesli_engine(:code)
|
|
96
|
+
|
|
97
|
+
# Rails main host app stylesheets
|
|
98
|
+
return 'application' if engine_code == 'root'
|
|
99
|
+
|
|
100
|
+
# Rails engines stylesheets
|
|
101
|
+
"#{engine_code}/#{stylesheet}"
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# print a custom icon for lesli
|
|
105
|
+
def lesli_svg(name)
|
|
106
|
+
content_tag("svg", width: "64px", height: "64px") do
|
|
107
|
+
"<use xlink:href='##{name}'></use>".html_safe
|
|
108
|
+
end
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
# Prints objects as JSON code
|
|
112
|
+
def dd object
|
|
113
|
+
content_tag(:pre) do
|
|
114
|
+
content_tag(:code) do
|
|
115
|
+
ERB::Util.html_escape JSON.pretty_generate(object.as_json)
|
|
116
|
+
end
|
|
117
|
+
end
|
|
6
118
|
end
|
|
7
119
|
end
|
|
8
120
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
5
|
-
Copyright (c)
|
|
5
|
+
Copyright (c) 2026, 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
|
|
@@ -68,29 +68,6 @@ module Lesli
|
|
|
68
68
|
end
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
def navigation_link_vue(path, label, icon = nil, reload: false)
|
|
72
|
-
# default vue router links for single page applications
|
|
73
|
-
html_element = "router-link"
|
|
74
|
-
html_options = { to: path, 'active-class': "navigation-link-active" }
|
|
75
|
-
|
|
76
|
-
# if reload is nedeed, we use a standard "a" tag
|
|
77
|
-
if reload
|
|
78
|
-
html_element = "a"
|
|
79
|
-
html_options = { href: path }
|
|
80
|
-
end
|
|
81
|
-
|
|
82
|
-
content_tag(html_element, html_options) do
|
|
83
|
-
# print a simple menu item (without icon)
|
|
84
|
-
concat content_tag(:span, label, class: "text iconless") unless icon
|
|
85
|
-
|
|
86
|
-
# print a full menu item if icon was requested
|
|
87
|
-
if icon
|
|
88
|
-
concat content_tag(:span, nil, class: icon)
|
|
89
|
-
concat content_tag(:span, label, class: "text")
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
end
|
|
93
|
-
|
|
94
71
|
# ADMINISTRATION
|
|
95
72
|
|
|
96
73
|
# 01.01 Admin engine
|
|
@@ -107,6 +84,12 @@ module Lesli
|
|
|
107
84
|
|
|
108
85
|
# SALES & MARKETING
|
|
109
86
|
|
|
87
|
+
# 02.02 Contacts engine
|
|
88
|
+
def navigation_engine_contacts(title: "Contacts", subtitle: "Customer Relationship Management")
|
|
89
|
+
return unless defined? LesliContacts
|
|
90
|
+
navigation_engine_item(title,subtitle,"contacts",lesli_contacts.root_path,controller_path.include?("lesli_contacts"))
|
|
91
|
+
end
|
|
92
|
+
|
|
110
93
|
# 02.04 House engine
|
|
111
94
|
def navigation_engine_house(title: "House", subtitle: "cloud_house/house-logo.svg")
|
|
112
95
|
return unless defined? CloudHouse
|
|
@@ -266,7 +249,7 @@ module Lesli
|
|
|
266
249
|
# SECURITY & PRIVACY
|
|
267
250
|
|
|
268
251
|
# 08.01 Shield engine
|
|
269
|
-
def navigation_engine_shield(title: "Shield", subtitle: "
|
|
252
|
+
def navigation_engine_shield(title: "Shield", subtitle: "Users & Security Management")
|
|
270
253
|
return unless defined? LesliShield
|
|
271
254
|
navigation_engine_item(title, subtitle, "shield", lesli_shield.root_path, controller_path.include?("lesli_shield"))
|
|
272
255
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
5
|
-
Copyright (c)
|
|
5
|
+
Copyright (c) 2026, 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,19 +19,36 @@ 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
|
|
26
|
-
@website https://www.lesli.
|
|
26
|
+
@website https://www.lesli.tech
|
|
27
27
|
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
28
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
-
// ·
|
|
30
|
+
// ·
|
|
31
31
|
=end
|
|
32
32
|
|
|
33
33
|
module Lesli
|
|
34
34
|
module SystemHelper
|
|
35
|
+
|
|
36
|
+
# build a url path to change locales
|
|
37
|
+
def language_url(locale)
|
|
38
|
+
"/lesli/language?locale=#{locale}"
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# return flag code according to locale code
|
|
42
|
+
def language_flag(locale)
|
|
43
|
+
locale = "gb" if locale.to_s == "en"
|
|
44
|
+
locale
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
# return the name of the language
|
|
48
|
+
def language_name(locale)
|
|
49
|
+
Lesli.config.locales.dig(locale) || "undefined"
|
|
50
|
+
end
|
|
51
|
+
|
|
35
52
|
# return the engine code of the controller that is handling the http request
|
|
36
53
|
def lesli_controller
|
|
37
54
|
controller_path.split("/")[0]
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
5
|
-
Copyright (c)
|
|
5
|
+
Copyright (c) 2026, 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
|
|
@@ -32,7 +32,24 @@ Building a better future, one line of code at a time.
|
|
|
32
32
|
|
|
33
33
|
module Lesli
|
|
34
34
|
module TurboHelper
|
|
35
|
-
|
|
35
|
+
|
|
36
|
+
def turbo_link_to body, url, html_options = {}
|
|
37
|
+
link_to(body, url, class: "link", data: { turbo_frame: '_top' })
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
# Meta-programming to define flash setter methods dynamically
|
|
41
|
+
# success("Everything worked!")
|
|
42
|
+
# danger("Oops, there was an error.")
|
|
43
|
+
# info("Just an informational message.")
|
|
44
|
+
# warning("This is a warning.")
|
|
45
|
+
[:info, :success, :warning, :danger].each do |flash_type|
|
|
46
|
+
define_method(flash_type) do |message|
|
|
47
|
+
flash[flash_type] = message
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def stream_notification_success(message)
|
|
52
|
+
success(message)
|
|
36
53
|
turbo_stream.replace("application-lesli-notifications") do
|
|
37
54
|
render("lesli/partials/application-lesli-notifications")
|
|
38
55
|
end
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
5
|
-
Copyright (c)
|
|
5
|
+
Copyright (c) 2026, 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,10 +33,6 @@ Building a better future, one line of code at a time.
|
|
|
33
33
|
module Lesli
|
|
34
34
|
module RequesterInterface
|
|
35
35
|
|
|
36
|
-
def set_path
|
|
37
|
-
@@engine_path = Lesli::Engine.routes.find_script_name({})
|
|
38
|
-
end
|
|
39
|
-
|
|
40
36
|
# Set the user language based on user_settings, session configuration or instance default locale
|
|
41
37
|
def set_locale
|
|
42
38
|
# get saved language in session, browser language or the default in config
|
|
@@ -76,28 +72,5 @@ module Lesli
|
|
|
76
72
|
}
|
|
77
73
|
}
|
|
78
74
|
end
|
|
79
|
-
|
|
80
|
-
def get_user_agent(as_string=true)
|
|
81
|
-
|
|
82
|
-
http_user_agent = request.env["HTTP_USER_AGENT"]
|
|
83
|
-
|
|
84
|
-
# parse user agent
|
|
85
|
-
user_agent = UserAgent.parse(http_user_agent)
|
|
86
|
-
|
|
87
|
-
user_agent_version = user_agent.version.to_a.first(2).join(".")
|
|
88
|
-
|
|
89
|
-
# return user agent as object
|
|
90
|
-
if as_string == false
|
|
91
|
-
return {
|
|
92
|
-
platform: user_agent.platform,
|
|
93
|
-
os: user_agent.os,
|
|
94
|
-
browser: user_agent.browser,
|
|
95
|
-
version: user_agent_version
|
|
96
|
-
}
|
|
97
|
-
end
|
|
98
|
-
|
|
99
|
-
# return user agent info as string
|
|
100
|
-
"#{user_agent.platform} #{user_agent.os} - #{user_agent.browser} #{user_agent_version}"
|
|
101
|
-
end
|
|
102
75
|
end
|
|
103
76
|
end
|