lesli 5.0.11 → 5.0.12
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/config/lesli_manifest.js +0 -13
- data/app/assets/icons/lesli/engine-security.svg +1 -0
- data/app/assets/icons/lesli/engine-shield.svg +1 -0
- data/app/assets/images/lesli/lesli-logo.svg +4 -0
- data/app/assets/stylesheets/lesli/templates/application.css +21862 -209
- data/app/assets/stylesheets/lesli/templates/public.css +19098 -1
- data/app/assets/stylesheets/lesli/users/confirmations.css +19219 -0
- data/app/assets/stylesheets/lesli/users/passwords.css +19202 -0
- data/app/assets/stylesheets/lesli/users/registrations.css +19594 -0
- data/app/assets/stylesheets/lesli/users/sessions.css +19594 -1
- data/app/controllers/lesli/abouts_controller.rb +12 -18
- data/app/controllers/lesli/application_controller.rb +25 -25
- data/app/controllers/lesli/application_lesli_controller.rb +5 -6
- data/app/controllers/lesli/interfaces/application/authorization.rb +1 -1
- data/app/controllers/lesli/interfaces/application/customization.rb +1 -1
- data/app/controllers/lesli/interfaces/application/requester.rb +2 -2
- data/app/controllers/lesli/interfaces/application/responder.rb +8 -8
- data/app/controllers/lesli/interfaces/controllers/actions.rb +250 -0
- data/app/controllers/lesli/interfaces/controllers/activities.rb +215 -0
- data/app/controllers/lesli/interfaces/controllers/discussions.rb +270 -0
- data/app/controllers/lesli/interfaces/controllers/files.rb +467 -0
- data/app/controllers/lesli/interfaces/controllers/subscribers.rb +234 -0
- data/app/helpers/lesli/assets_helper.rb +4 -4
- data/app/helpers/lesli/navigation_helper.rb +38 -81
- data/app/lib/lesli/system.rb +4 -3
- data/app/models/concerns/account_initializer.rb +46 -42
- data/{lib/scss/devise/registrations.scss → app/models/lesli/account/detail.rb} +7 -3
- data/app/models/lesli/account.rb +12 -5
- data/app/models/lesli/cloud_object/action.rb +70 -0
- data/app/models/lesli/cloud_object/activity.rb +311 -0
- data/app/models/lesli/cloud_object/custom_field.rb +158 -0
- data/app/models/lesli/cloud_object/discussion.rb +219 -0
- data/app/models/lesli/cloud_object/subscriber.rb +186 -0
- data/app/models/lesli/shared/dashboard.rb +16 -5
- data/app/models/lesli/user/session.rb +0 -2
- data/app/models/lesli/user.rb +13 -13
- data/app/operators/lesli/user_registration_operator.rb +3 -3
- data/app/views/lesli/layouts/application-devise.html.erb +6 -6
- data/app/views/lesli/layouts/application-lesli.html.erb +1 -1
- data/app/views/lesli/partials/_application-data.html.erb +2 -1
- data/app/views/lesli/partials/_application-lesli-engines.html.erb +14 -39
- data/app/views/lesli/partials/_application-lesli-header.html.erb +4 -4
- data/app/views/lesli/partials/_application-lesli-icons.html.erb +1 -1
- data/app/views/lesli/partials/_application-lesli-panels.html.erb +7 -7
- data/app/views/lesli/wrappers/_application-devise.html.erb +5 -7
- data/config/initializers/devise.rb +335 -335
- data/config/initializers/lesli.rb +2 -1
- data/config/locales/translations.en.yml +4 -0
- data/config/locales/translations.es.yml +4 -0
- data/config/locales/translations.fr.yml +28 -0
- data/config/locales/translations.it.yml +28 -0
- data/config/locales/translations.pt.yml +28 -0
- data/config/routes.rb +1 -10
- data/db/migrate/{v1.0/0010003010_create_lesli_user_details.rb → v1/0010000110_create_lesli_accounts.rb} +19 -13
- data/db/migrate/{v1.0/0010000110_create_lesli_accounts.rb → v1/0010001010_create_lesli_account_details.rb} +5 -7
- data/db/migrate/{v1.0/0010001010_create_lesli_account_settings.rb → v1/0010001110_create_lesli_account_settings.rb} +2 -2
- data/db/seed/development/accounts.rb +10 -7
- data/db/seed/development/users.rb +20 -20
- data/db/seed/production/accounts.rb +10 -7
- data/lib/lesli/engine.rb +2 -12
- data/lib/lesli/version.rb +2 -2
- data/lib/lesli.rb +0 -1
- data/lib/scss/cloud-objects/discussion.scss +8 -5
- data/lib/scss/layouts/application-header.scss +3 -1
- data/lib/scss/layouts/application-navbar.scss +2 -1
- data/lib/scss/{elements/msg.scss → overrides/notification.scss} +16 -18
- data/lib/scss/pages/devise-simple.scss +4 -2
- data/lib/scss/pages/devise.scss +111 -107
- data/lib/scss/panels/panel-notification.scss +1 -1
- data/lib/scss/panels/{panel-ticket.scss → panel-support-ticket.scss} +3 -4
- data/lib/scss/templates/application.scss +7 -5
- data/lib/tasks/lesli/controllers.rake +1 -1
- data/lib/tasks/lesli/db.rake +24 -12
- data/lib/tasks/lesli_tasks.rake +6 -6
- data/lib/vue/application.js +13 -12
- data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/content.vue +10 -8
- data/lib/vue/cloudobjects/discussion/element.vue +170 -0
- data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/filters.vue +1 -1
- data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/new.vue +20 -16
- data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion.vue +25 -24
- data/lib/vue/{refactor/stores/cloudobjects → cloudobjects/stores}/discussion.js +7 -16
- data/lib/vue/layouts/application-header.vue +5 -5
- data/lib/vue/panels/{panel-notifications.vue → panel-bell-notifications.vue} +15 -19
- data/lib/vue/panels/panel-support-tickets.vue +161 -0
- data/lib/vue/panels/stores/bell-notifications.js +46 -0
- data/lib/vue/panels/stores/support-tickets.js +103 -0
- data/lib/vue/shared/dashboards/apps/edit.vue +10 -10
- data/lib/vue/shared/dashboards/components/form.vue +31 -40
- data/lib/vue/shared/stores/dashboard.js +2 -0
- data/lib/vue/shared/stores/layout.js +2 -1
- data/lib/{scss/devise/confirmations.scss → vue/shared/stores/users.js} +22 -21
- data/lib/vue/stores/translations.json +109 -2
- data/lib/webpack/base.js +9 -8
- data/lib/webpack/core.js +8 -6
- data/readme.md +16 -15
- metadata +49 -76
- data/app/assets/icons/lesli/engine-guard.svg +0 -1
- data/app/assets/javascripts/lesli/users/sessions.js +0 -1
- data/app/controllers/users/confirmations_controller.rb +0 -66
- data/app/controllers/users/omniauth_callbacks_controller.rb +0 -30
- data/app/controllers/users/passwords_controller.rb +0 -71
- data/app/controllers/users/registrations_controller.rb +0 -141
- data/app/controllers/users/sessions_controller.rb +0 -141
- data/app/controllers/users/unlocks_controller.rb +0 -30
- data/app/views/devise/confirmations/new.html.erb +0 -2
- data/app/views/devise/confirmations/show.html.erb +0 -63
- data/app/views/devise/mailer/confirmation_instructions.html.erb +0 -5
- data/app/views/devise/mailer/email_changed.html.erb +0 -7
- data/app/views/devise/mailer/password_change.html.erb +0 -3
- data/app/views/devise/mailer/reset_password_instructions.html.erb +0 -8
- data/app/views/devise/mailer/unlock_instructions.html.erb +0 -7
- data/app/views/devise/passwords/edit.html.erb +0 -79
- data/app/views/devise/passwords/new.html.erb +0 -75
- data/app/views/devise/registrations/edit.html.erb +0 -43
- data/app/views/devise/registrations/new.html.erb +0 -147
- data/app/views/devise/sessions/new.html.erb +0 -114
- data/app/views/devise/shared/_demo.html.erb +0 -7
- data/app/views/devise/shared/_error_messages.html.erb +0 -15
- data/app/views/devise/shared/_links.html.erb +0 -96
- data/app/views/devise/unlocks/new.html.erb +0 -16
- data/db/migrate/v1.0/0010000210_create_lesli_roles.rb +0 -59
- data/db/migrate/v1.0/0010000310_create_lesli_users.rb +0 -97
- data/db/migrate/v1.0/0010003110_create_lesli_user_settings.rb +0 -44
- data/db/migrate/v1.0/0010003210_create_lesli_user_sessions.rb +0 -55
- data/db/migrate/v1.0/0010003410_create_lesli_user_powers.rb +0 -43
- data/db/migrate/v1.0/0010004010_create_lesli_user_logs.rb +0 -45
- data/db/migrate/v1.0/0010005010_create_lesli_descriptors.rb +0 -44
- data/db/migrate/v1.0/0010005110_create_lesli_descriptor_privileges.rb +0 -45
- data/db/migrate/v1.0/0010005210_create_lesli_descriptor_activities.rb +0 -49
- data/db/migrate/v1.0/0010005510_create_lesli_role_powers.rb +0 -51
- data/db/migrate/v1.0/0010005710_create_lesli_role_privileges.rb +0 -45
- data/lib/lesli/routing.rb +0 -26
- data/lib/scss/components/editor-richtext.scss +0 -88
- data/lib/scss/devise/oauth.scss +0 -34
- data/lib/scss/devise/passwords.scss +0 -33
- data/lib/scss/devise/sessions.scss +0 -35
- data/lib/scss/elements/avatar.scss +0 -48
- data/lib/scss/elements/calendar.scss +0 -47
- data/lib/scss/elements/toggle.scss +0 -102
- data/lib/vue/devise/confirmations.js +0 -33
- data/lib/vue/devise/passwords.js +0 -137
- data/lib/vue/devise/registrations.js +0 -157
- data/lib/vue/devise/sessions.js +0 -148
- data/lib/vue/panels/panel-tickets.vue +0 -181
- data/lib/vue/refactor/shared/cloudobjects/discussion/element.vue +0 -132
- data/lib/vue/shared/stores/account.js +0 -113
- /data/app/assets/icons/lesli/{engine-driver.svg → engine-calendar.svg} +0 -0
- /data/db/migrate/{v1.0 → v1}/0010000610_create_lesli_system_controllers.rb +0 -0
- /data/db/migrate/{v1.0 → v1}/0010000710_create_lesli_system_controller_actions.rb +0 -0
- /data/db/migrate/{v1.0 → v1}/0010001210_create_lesli_account_activities.rb +0 -0
- /data/db/migrate/{v1.0 → v1}/0010001410_create_lesli_account_logs.rb +0 -0
|
@@ -0,0 +1,234 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
|
|
3
|
+
Lesli
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2023, 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 · Your Smart Business Assistant.
|
|
21
|
+
|
|
22
|
+
Made with ♥ by https://www.lesli.tech
|
|
23
|
+
Building a better future, one line of code at a time.
|
|
24
|
+
|
|
25
|
+
@contact hello@lesli.tech
|
|
26
|
+
@website https://lesli.tech
|
|
27
|
+
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
|
+
|
|
29
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
+
// ·
|
|
31
|
+
|
|
32
|
+
=end
|
|
33
|
+
module Lesli
|
|
34
|
+
module Interfaces
|
|
35
|
+
module Controllers
|
|
36
|
+
module Subscribers
|
|
37
|
+
|
|
38
|
+
# @return [Json] Json that contains a list of all subscribers related to a *cloud_object*
|
|
39
|
+
# @description Retrieves and returns all subscribers associated to a *cloud_object*. The id of the
|
|
40
|
+
# *cloud_object* is within the *params* attribute
|
|
41
|
+
# @example
|
|
42
|
+
# # Executing this controller's action from javascript's frontend
|
|
43
|
+
# let ticket_id = 1;
|
|
44
|
+
# this.http.get(`127.0.0.1/help/tickets/${ticket_id}/subscribers`);
|
|
45
|
+
def index
|
|
46
|
+
subscriber_model = subscriber_model() # If there is a custom subscriber model, it must be returned in this method
|
|
47
|
+
cloud_object_model = subscriber_model.cloud_object_model
|
|
48
|
+
@cloud_object = cloud_object_model.find_by(id: params["#{cloud_object_model.name.demodulize.underscore}_id".to_sym])
|
|
49
|
+
return respond_with_not_found unless @cloud_object
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
target_user = current_user.account.users.find_by(id: params[:users_id]) if params[:users_id]
|
|
53
|
+
target_user = current_user unless target_user
|
|
54
|
+
|
|
55
|
+
actions = subscriber_model.subscription_actions(
|
|
56
|
+
@cloud_object,
|
|
57
|
+
target_user
|
|
58
|
+
)
|
|
59
|
+
respond_with_successful(actions)
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @controller_action_param :action [String] A string that represent a valid action present in the *Subscriber* model
|
|
63
|
+
# @controller_action_param :notification_type [String] A string that represents a valid notification_type
|
|
64
|
+
# present in the *Subscriber* model
|
|
65
|
+
# @return [Json] Json that contains wheter the creation of the subscriber was successful or not.
|
|
66
|
+
# If it is not successful, it returs an error message
|
|
67
|
+
# @description Creates a new subscriber associated to a *cloud_object* using *current_user* as the subscriber.
|
|
68
|
+
# The id of the *cloud_object* is within the *params* attribute
|
|
69
|
+
# @example
|
|
70
|
+
# # Executing this controller's action from javascript's frontend
|
|
71
|
+
# let ticket_id = 1;
|
|
72
|
+
# let data = {
|
|
73
|
+
# subscriber: {
|
|
74
|
+
# notification_type: "web",
|
|
75
|
+
# action: "ticket_closed"
|
|
76
|
+
# }
|
|
77
|
+
# };
|
|
78
|
+
# this.http.post(`127.0.0.1/help/tickets/${ticket_id}/subscribers`, data);
|
|
79
|
+
def create
|
|
80
|
+
subscriber_model = subscriber_model() # If there is a custom subscriber model, it must be returned in this method
|
|
81
|
+
cloud_object_model = subscriber_model.cloud_object_model
|
|
82
|
+
|
|
83
|
+
target_user = current_user.account.users.find_by(id: params[:users_id]) if params[:users_id]
|
|
84
|
+
target_user = current_user unless target_user
|
|
85
|
+
|
|
86
|
+
set_cloud_object
|
|
87
|
+
new_subscriber_params = subscriber_params.merge(
|
|
88
|
+
user_creator: target_user,
|
|
89
|
+
cloud_object: @cloud_object
|
|
90
|
+
)
|
|
91
|
+
cloud_object_subscriber = subscriber_model.new(new_subscriber_params)
|
|
92
|
+
|
|
93
|
+
if cloud_object_subscriber.save
|
|
94
|
+
respond_with_successful(cloud_object_subscriber)
|
|
95
|
+
else
|
|
96
|
+
respond_with_error(cloud_object_subscriber.errors.full_messages.to_sentence)
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
# @controller_action_param :action [String] A string that represent a valid action present in the *Subscriber* model
|
|
101
|
+
# @controller_action_param :notification_type [String] A string that represents a valid notification_type
|
|
102
|
+
# @return [Json] Json that contains wheter the update of the subscriber was successful or not.
|
|
103
|
+
# If it is not successful, it returs an error message
|
|
104
|
+
# @description Updates the subscriber based on the id of the *cloud_object* and its own id.
|
|
105
|
+
# @example
|
|
106
|
+
# # Executing this controller's action from javascript's frontend
|
|
107
|
+
# let ticket_id = 1;
|
|
108
|
+
# let subscriber_id = 22;
|
|
109
|
+
# data = {
|
|
110
|
+
# subscriber: {
|
|
111
|
+
# notification_type: "email"
|
|
112
|
+
# }
|
|
113
|
+
# };
|
|
114
|
+
# this.http.patch(`127.0.0.1/help/tickets/${ticket_id}/subscribers/${subscriber_id}`, data);
|
|
115
|
+
def update
|
|
116
|
+
set_subscriber
|
|
117
|
+
return respond_with_not_found unless @subscriber
|
|
118
|
+
|
|
119
|
+
if @subscriber.update(subscriber_params)
|
|
120
|
+
respond_with_successful
|
|
121
|
+
else
|
|
122
|
+
respond_with_error(@subscriber.errors.full_messages.to_sentence)
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
|
|
126
|
+
# @return [Json] A response that contains wheter the subscriber was deleted or not.
|
|
127
|
+
# If it is not successful, it returns an error message
|
|
128
|
+
# @description Deletes a subscriber from the database based on the id of the *cloud_object* and its own id.
|
|
129
|
+
# @example
|
|
130
|
+
# # Executing this controller's action from javascript's frontend
|
|
131
|
+
# let ticket_id = 1;
|
|
132
|
+
# let subscriber_id = 22;
|
|
133
|
+
# this.http.delete(`127.0.0.1/help/tickets/${ticket_id}/subscribers/${subscriber_id}`);
|
|
134
|
+
def destroy
|
|
135
|
+
set_subscriber
|
|
136
|
+
return respond_with_not_found unless @subscriber
|
|
137
|
+
|
|
138
|
+
if @subscriber.destroy
|
|
139
|
+
respond_with_successful
|
|
140
|
+
else
|
|
141
|
+
respond_with_error(@subscriber.errors.full_messages.to_sentence)
|
|
142
|
+
end
|
|
143
|
+
end
|
|
144
|
+
|
|
145
|
+
protected
|
|
146
|
+
|
|
147
|
+
# @return [void]
|
|
148
|
+
# @descriptions Sets the variable @cloud_object based on the paremeters send in the URL. If no,
|
|
149
|
+
# cloud_object is found or it is not within the current_user's account, nil is used instead
|
|
150
|
+
# @example
|
|
151
|
+
# # Imagine you are inside CloudFocus::Task::DiscussionsController
|
|
152
|
+
# puts @cloud_object # will display nil
|
|
153
|
+
# set_cloud_object
|
|
154
|
+
# puts @cloud_object # Will display an instance of CloudFocus::Task
|
|
155
|
+
def set_cloud_object
|
|
156
|
+
subscriber_model = subscriber_model() # If there is a custom subscriber model, it must be returned in this method
|
|
157
|
+
cloud_object_model = subscriber_model.cloud_object_model
|
|
158
|
+
account_model = cloud_object_model.reflect_on_association(:account).klass
|
|
159
|
+
|
|
160
|
+
@cloud_object = cloud_object_model.find_by(
|
|
161
|
+
id: params["#{cloud_object_model.name.demodulize.underscore}_id".to_sym],
|
|
162
|
+
"#{account_model.table_name}_id".to_sym => current_user.account.id
|
|
163
|
+
)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
# @return [void]
|
|
167
|
+
# @description Sets the variable @subscriber. The variable contains the subscription
|
|
168
|
+
# to be updated based on the id of the *cloud_object* and the id of the *subscriber*
|
|
169
|
+
# @example
|
|
170
|
+
# #suppose params[:ticket_id] = 1
|
|
171
|
+
# #suppose params[:id] = 44
|
|
172
|
+
# puts @subscriber # will display nil
|
|
173
|
+
# set_subscriber
|
|
174
|
+
# puts @subscriber # will display an instance of CloudHelp:Ticket::Subscriber
|
|
175
|
+
def set_subscriber
|
|
176
|
+
subscriber_model = subscriber_model() # If there is a custom subscriber model, it must be returned in this method
|
|
177
|
+
cloud_object_model = subscriber_model.cloud_object_model
|
|
178
|
+
account_model = cloud_object_model.reflect_on_association(:account).klass
|
|
179
|
+
|
|
180
|
+
@subscriber = subscriber_model.joins(:cloud_object).where(
|
|
181
|
+
"#{cloud_object_model.table_name}.id = #{params["#{cloud_object_model.name.demodulize.underscore}_id".to_sym]}",
|
|
182
|
+
"#{cloud_object_model.table_name}.#{account_model.table_name}_id = #{current_user.account.id}"
|
|
183
|
+
).find_by(
|
|
184
|
+
id: params[:id]
|
|
185
|
+
)
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
# @return [Parameters] Allowed parameters for the subscriber
|
|
189
|
+
# @description Sanitizes the parameters received from an HTTP call to only allow the specified ones.
|
|
190
|
+
# Allowed params are _:action_, _:notification_type_.
|
|
191
|
+
# @example
|
|
192
|
+
# # supose params contains {
|
|
193
|
+
# # "subscriber": {
|
|
194
|
+
# # "id": 5,
|
|
195
|
+
# # "action": "ticket_created",
|
|
196
|
+
# # "notification_type": "email",
|
|
197
|
+
# # "random_param": 5
|
|
198
|
+
# # }
|
|
199
|
+
# #}
|
|
200
|
+
# subscriber_params = subscriber_params
|
|
201
|
+
# puts subscriber_params
|
|
202
|
+
# # will remove the _id_ and _random_param_ fields and only print {
|
|
203
|
+
# # "subscriber": {
|
|
204
|
+
# # "action": "ticket_created",
|
|
205
|
+
# # "notification_type": "email"
|
|
206
|
+
# # }
|
|
207
|
+
# #}
|
|
208
|
+
def subscriber_params
|
|
209
|
+
subscriber_model = subscriber_model() # If there is a custom subscriber model, it must be returned in this method
|
|
210
|
+
cloud_object_model = subscriber_model.cloud_object_model
|
|
211
|
+
|
|
212
|
+
params.require(
|
|
213
|
+
"#{cloud_object_model.name.demodulize.underscore}_subscriber".to_sym
|
|
214
|
+
).permit(
|
|
215
|
+
:action,
|
|
216
|
+
:notification_type
|
|
217
|
+
)
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# @return [CloudObject::Subscriber] The subscriber model that the controller will handle
|
|
221
|
+
# @descriptions Constantizes and returns the subscriber model associated to this controller. This method
|
|
222
|
+
# can be overrided by the implementation in the child controller
|
|
223
|
+
# @example
|
|
224
|
+
# # Suppose you are inside CloudHelp::Ticket::SubscriberController
|
|
225
|
+
# puts subscriber_model().new
|
|
226
|
+
# # This will display a new instance of CloudHelp::Ticket::Discussion
|
|
227
|
+
def subscriber_model
|
|
228
|
+
self.class.name.gsub("Controller","").singularize.constantize
|
|
229
|
+
end
|
|
230
|
+
end
|
|
231
|
+
end
|
|
232
|
+
end
|
|
233
|
+
end
|
|
234
|
+
|
|
@@ -46,11 +46,11 @@ module Lesli
|
|
|
46
46
|
|
|
47
47
|
# Return a string path to load the main engine stylesheet
|
|
48
48
|
def application_stylesheet_engine_path
|
|
49
|
-
|
|
49
|
+
lesli_engine = lesli_engine(:code)
|
|
50
50
|
return "administration/application" if is_lesli_administration?
|
|
51
51
|
return "onboardings/application" if is_lesli_onboarding?
|
|
52
52
|
|
|
53
|
-
"#{
|
|
53
|
+
"#{lesli_engine}/application"
|
|
54
54
|
end
|
|
55
55
|
|
|
56
56
|
# Return a string path to load the main javascript app of the engine
|
|
@@ -58,11 +58,11 @@ module Lesli
|
|
|
58
58
|
# get the namespace to load specific javascript file
|
|
59
59
|
# for engine or specific javascript file for core controller
|
|
60
60
|
path_segments = controller_path.split("/")
|
|
61
|
-
|
|
61
|
+
lesli_engine = path_segments.shift
|
|
62
62
|
|
|
63
63
|
return "onboardings/application" if is_lesli_onboarding?
|
|
64
64
|
|
|
65
|
-
"#{
|
|
65
|
+
"#{lesli_engine}/application"
|
|
66
66
|
end
|
|
67
67
|
|
|
68
68
|
def javascript_googlemaps_sdk
|
|
@@ -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
|
|
@@ -66,134 +66,94 @@ module Lesli
|
|
|
66
66
|
end
|
|
67
67
|
end
|
|
68
68
|
|
|
69
|
-
#
|
|
70
|
-
|
|
69
|
+
# ADMINISTRATION
|
|
70
|
+
|
|
71
|
+
# 01.01 Admin engine
|
|
72
|
+
def navigation_engine_admin(title: "Administration", subtitle: "Administration area.")
|
|
71
73
|
return unless defined? LesliAdmin
|
|
72
|
-
navigation_engine_item(title,
|
|
74
|
+
navigation_engine_item(title,subtitle,"admin",lesli_admin.root_path,controller_path.include?("lesli_admin"))
|
|
73
75
|
end
|
|
74
76
|
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
# 01.01 Team engine
|
|
77
|
+
# 01.02 Team engine
|
|
78
78
|
def navigation_engine_team(title: "Team", subtitle: "Human Resources Management")
|
|
79
79
|
return unless defined? CloudTeam
|
|
80
|
-
|
|
81
|
-
navigation_engine_item(title, subtitle, "team", cloud_team.root_path,
|
|
82
|
-
controller_path.include?("cloud_team"))
|
|
80
|
+
navigation_engine_item(title,subtitle,"team",cloud_team.root_path,controller_path.include?("cloud_team"))
|
|
83
81
|
end
|
|
84
82
|
|
|
85
83
|
# SALES & MARKETING
|
|
86
84
|
|
|
87
|
-
# 02.03 Drop engine
|
|
88
|
-
def navigation_engine_word(title: "Word", subtitle: "Content Management System")
|
|
89
|
-
return unless defined? CloudWord
|
|
90
|
-
|
|
91
|
-
navigation_engine_item(title, subtitle, "word", cloud_word.root_path,
|
|
92
|
-
controller_path.include?("cloud_word"))
|
|
93
|
-
end
|
|
94
|
-
|
|
95
85
|
# 02.04 House engine
|
|
96
86
|
def navigation_engine_house(title: "House", subtitle: "cloud_house/house-logo.svg")
|
|
97
87
|
return unless defined? CloudHouse
|
|
98
|
-
|
|
99
|
-
navigation_engine_item(title, subtitle, "house", cloud_house.root_path,
|
|
100
|
-
controller_path.include?("cloud_house"))
|
|
88
|
+
navigation_engine_item(title,subtitle,"house",cloud_house.root_path,controller_path.include?("cloud_house"))
|
|
101
89
|
end
|
|
102
90
|
|
|
103
91
|
# 02.05 Mailer engine
|
|
104
92
|
def navigation_engine_mailer(title: "Mailer", subtitle: "Email automation system")
|
|
105
93
|
return unless defined? CloudMailer
|
|
106
|
-
|
|
107
|
-
navigation_engine_item(title, subtitle, "mailer", cloud_mailer.root_path,
|
|
108
|
-
controller_path.include?("cloud_mailer"))
|
|
94
|
+
navigation_engine_item(title,subtitle,"mailer",cloud_mailer.root_path,controller_path.include?("cloud_mailer"))
|
|
109
95
|
end
|
|
110
96
|
|
|
111
97
|
# 02.08 Proposal engine
|
|
112
98
|
def navigation_engine_proposal(title: "Proposal", subtitle: "cloud_proposal/proposal-logo.svg")
|
|
113
99
|
return unless defined? CloudProposal
|
|
114
|
-
|
|
115
|
-
navigation_engine_item(title, subtitle, "proposal", cloud_proposal.root_path,
|
|
116
|
-
controller_path.include?("cloud_proposal"))
|
|
100
|
+
navigation_engine_item(title,subtitle,"proposal",cloud_proposal.root_path,controller_path.include?("cloud_proposal"))
|
|
117
101
|
end
|
|
118
102
|
|
|
119
103
|
# PRODUCTIVITY & TEAMWORK
|
|
120
104
|
|
|
121
|
-
# 03.01
|
|
122
|
-
def
|
|
123
|
-
return unless defined?
|
|
124
|
-
navigation_engine_item(title, subtitle, "
|
|
125
|
-
end
|
|
126
|
-
|
|
127
|
-
# 03.02 Work engine
|
|
128
|
-
def navigation_engine_work(title: "Work", subtitle: "Dynamic Project Management")
|
|
129
|
-
return unless defined? CloudWork
|
|
130
|
-
|
|
131
|
-
navigation_engine_item(title, subtitle, "work", cloud_work.root_path,
|
|
132
|
-
controller_path.include?("cloud_work"))
|
|
105
|
+
# 03.01 Calendar engine
|
|
106
|
+
def navigation_engine_calendar(title: "Calendar", subtitle: "Unified calendar app")
|
|
107
|
+
return unless defined? LesliCalendar
|
|
108
|
+
navigation_engine_item(title, subtitle, "calendar", lesli_calendar.root_path, controller_path.include?("lesli_calendar"))
|
|
133
109
|
end
|
|
134
110
|
|
|
135
111
|
# 03.03 Focus engine
|
|
136
112
|
def navigation_engine_focus(title: "Tasks", subtitle: "Task Management")
|
|
137
113
|
return unless defined? CloudFocus
|
|
138
|
-
|
|
139
|
-
navigation_engine_item(title, subtitle, "focus", cloud_focus.root_path,
|
|
140
|
-
controller_path.include?("cloud_focus"))
|
|
114
|
+
navigation_engine_item(title,subtitle,"focus",cloud_focus.root_path,controller_path.include?("cloud_focus"))
|
|
141
115
|
end
|
|
142
116
|
|
|
143
117
|
# 03.05 Letter engine
|
|
144
118
|
def navigation_engine_letter(title: "Letter", subtitle: "Notes & Notebooks")
|
|
145
119
|
return unless defined? LesliLetter
|
|
146
|
-
|
|
147
|
-
navigation_engine_item(title, subtitle, "letter", lesli_letter.root_path,
|
|
148
|
-
controller_path.include?("lesli_letter"))
|
|
120
|
+
navigation_engine_item(title,subtitle,"letter",lesli_letter.root_path,controller_path.include?("lesli_letter"))
|
|
149
121
|
end
|
|
150
122
|
|
|
151
123
|
# 03.06 Dashboard engine
|
|
152
124
|
def navigation_engine_dashboard(title: "Dashboard", subtitle: "Smart business assistant")
|
|
153
125
|
return unless defined? LesliDashboard
|
|
154
|
-
|
|
155
|
-
navigation_engine_item(title, subtitle, "dashboard", lesli_dashboard.root_path,
|
|
156
|
-
controller_path.include?("lesli_dashboard"))
|
|
126
|
+
navigation_engine_item(title,subtitle,"dashboard",lesli_dashboard.root_path,controller_path.include?("lesli_dashboard"))
|
|
157
127
|
end
|
|
158
128
|
|
|
159
129
|
# 03.07 Social engine
|
|
160
130
|
def navigation_engine_social(title: "Social", subtitle: "Team social network")
|
|
161
131
|
return unless defined? CloudSocial
|
|
162
|
-
|
|
163
|
-
navigation_engine_item(title, subtitle, "social", cloud_social.root_path,
|
|
164
|
-
controller_path.include?("cloud_social"))
|
|
132
|
+
navigation_engine_item(title,subtitle,"social",cloud_social.root_path,controller_path.include?("cloud_social"))
|
|
165
133
|
end
|
|
166
134
|
|
|
167
135
|
# 03.08 Bell engine
|
|
168
|
-
def navigation_engine_bell(title: "Notifications", subtitle: "
|
|
136
|
+
def navigation_engine_bell(title: "Notifications", subtitle: "Notifications & Announcements")
|
|
169
137
|
return unless defined? LesliBell
|
|
170
|
-
|
|
171
|
-
navigation_engine_item(title, subtitle, "bell", lesli_bell.root_path,
|
|
172
|
-
controller_path.include?("lesli_bell"))
|
|
138
|
+
navigation_engine_item(title, subtitle, "bell", lesli_bell.root_path, controller_path.include?("lesli_bell"))
|
|
173
139
|
end
|
|
174
140
|
|
|
175
141
|
# 03.09 Time engine
|
|
176
142
|
def navigation_engine_time(title: "Time managment", subtitle: "Track your time")
|
|
177
143
|
return unless defined? CloudTime
|
|
178
|
-
|
|
179
|
-
navigation_engine_item(title, subtitle, "time", cloud_time.root_path,
|
|
180
|
-
controller_path.include?("cloud_time"))
|
|
144
|
+
navigation_engine_item(title,subtitle,"time",cloud_time.root_path,controller_path.include?("cloud_time"))
|
|
181
145
|
end
|
|
182
146
|
|
|
183
147
|
# 03.10 Talk engine
|
|
184
148
|
def navigation_engine_talk(title: "Talk", subtitle: "Real-time communication")
|
|
185
149
|
return unless defined? CloudTalk
|
|
186
|
-
|
|
187
|
-
navigation_engine_item(title, subtitle, "talk", cloud_talk.root_path,
|
|
188
|
-
controller_path.include?("cloud_talk"))
|
|
150
|
+
navigation_engine_item(title,subtitle,"talk",cloud_talk.root_path,controller_path.include?("cloud_talk"))
|
|
189
151
|
end
|
|
190
152
|
|
|
191
153
|
# 03.11 Storage engine
|
|
192
154
|
def navigation_engine_storage(title: "Storage", subtitle: "Cloud files management")
|
|
193
155
|
return unless defined? CloudStorage
|
|
194
|
-
|
|
195
|
-
navigation_engine_item(title, subtitle, "storage", cloud_storage.root_path,
|
|
196
|
-
controller_path.include?("cloud_storage"))
|
|
156
|
+
navigation_engine_item(title,subtitle,"storage",cloud_storage.root_path,controller_path.include?("cloud_storage"))
|
|
197
157
|
end
|
|
198
158
|
|
|
199
159
|
# FINANCE
|
|
@@ -224,14 +184,13 @@ module Lesli
|
|
|
224
184
|
|
|
225
185
|
# ANALYTICS
|
|
226
186
|
|
|
227
|
-
# 05.
|
|
228
|
-
def
|
|
229
|
-
return unless defined?
|
|
230
|
-
|
|
231
|
-
navigation_engine_item(title, subtitle, "insights", cloud_insights.root_path,
|
|
232
|
-
controller_path.include?("cloud_insights"))
|
|
187
|
+
# 05.02 Audit engine
|
|
188
|
+
def navigation_engine_audit(title: "Audit", subtitle: "Activity, logs, security and more")
|
|
189
|
+
return unless defined? LesliAudit
|
|
190
|
+
navigation_engine_item(title, subtitle, "audit", lesli_audit.root_path, controller_path.include?("lesli_audit"))
|
|
233
191
|
end
|
|
234
192
|
|
|
193
|
+
|
|
235
194
|
# INTELLIGENCE
|
|
236
195
|
|
|
237
196
|
# 06.06 Scraper engine
|
|
@@ -277,21 +236,19 @@ module Lesli
|
|
|
277
236
|
|
|
278
237
|
# SECURITY & PRIVACY
|
|
279
238
|
|
|
280
|
-
# 08.01
|
|
281
|
-
def
|
|
282
|
-
return unless defined?
|
|
283
|
-
navigation_engine_item(title, subtitle, "
|
|
284
|
-
controller_path.include?("lesli_guard"))
|
|
239
|
+
# 08.01 Shield engine
|
|
240
|
+
def navigation_engine_shield(title: "Shield", subtitle: "Authentication & Authorization.")
|
|
241
|
+
return unless defined? LesliShield
|
|
242
|
+
navigation_engine_item(title, subtitle, "shield", lesli_shield.root_path, controller_path.include?("lesli_shield"))
|
|
285
243
|
end
|
|
286
244
|
|
|
287
|
-
# 08.
|
|
288
|
-
def
|
|
289
|
-
return unless defined?
|
|
290
|
-
|
|
291
|
-
navigation_engine_item(title, subtitle, "audit", lesli_audit.root_path,
|
|
292
|
-
controller_path.include?("lesli_audit"))
|
|
245
|
+
# 08.02 Security engine
|
|
246
|
+
def navigation_engine_security(title: "Security", subtitle: "Users, Privileges & Access Management.")
|
|
247
|
+
return unless defined? LesliSecurity
|
|
248
|
+
navigation_engine_item(title, subtitle, "security", lesli_security.root_path, controller_path.include?("lesli_security"))
|
|
293
249
|
end
|
|
294
250
|
|
|
251
|
+
|
|
295
252
|
# INTEGRATIONS
|
|
296
253
|
|
|
297
254
|
# 09.01 Babel engine
|
data/app/lib/lesli/system.rb
CHANGED
|
@@ -83,14 +83,15 @@ module Lesli
|
|
|
83
83
|
|
|
84
84
|
LESLI_ENGINES = [
|
|
85
85
|
"Lesli",
|
|
86
|
+
"LesliBell",
|
|
86
87
|
"LesliAdmin",
|
|
87
88
|
"LesliBabel",
|
|
88
89
|
"LesliAudit",
|
|
89
|
-
"
|
|
90
|
-
"LesliDriver",
|
|
91
|
-
"LesliGuard",
|
|
90
|
+
"LesliShield",
|
|
92
91
|
"LesliLetter",
|
|
93
92
|
"LesliSupport",
|
|
93
|
+
"LesliSecurity",
|
|
94
|
+
"LesliCalendar",
|
|
94
95
|
"LesliDashboard"
|
|
95
96
|
]
|
|
96
97
|
end
|
|
@@ -37,24 +37,41 @@ module AccountInitializer
|
|
|
37
37
|
# initialize minimum resources needed for the account
|
|
38
38
|
def initialize_account
|
|
39
39
|
|
|
40
|
+
return unless defined?(LesliSecurity)
|
|
41
|
+
|
|
40
42
|
# create initial descriptors
|
|
41
43
|
descriptor_owner = self.descriptors.find_or_create_by(name: "owner")
|
|
42
44
|
descriptor_admin = self.descriptors.find_or_create_by(name: "admin")
|
|
43
45
|
descriptor_profile = self.descriptors.find_or_create_by(name: "profile")
|
|
44
46
|
|
|
45
47
|
# create default roles for the new account
|
|
46
|
-
owner = self.roles.
|
|
48
|
+
owner = self.roles.create_with({
|
|
49
|
+
active: true,
|
|
50
|
+
object_level_permission: 2147483647
|
|
51
|
+
}).find_or_create_by(:name => "owner")
|
|
47
52
|
|
|
48
53
|
# platform administrator role
|
|
49
|
-
admin = self.roles.
|
|
54
|
+
admin = self.roles.create_with({
|
|
55
|
+
active: true, object_level_permission: 100000
|
|
56
|
+
}).find_or_create_by({ name: "admin" })
|
|
50
57
|
|
|
51
58
|
# access only to user profile
|
|
52
|
-
limited = self.roles.
|
|
59
|
+
limited = self.roles.create_with({
|
|
60
|
+
active: true, object_level_permission: 10, path_default: "/administration/profile"
|
|
61
|
+
}).find_or_create_by({ name: "limited" })
|
|
53
62
|
|
|
54
63
|
# assign descriptors with appropriate privileges
|
|
55
|
-
owner.powers.
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
owner.powers.create_with({
|
|
65
|
+
plist: true, pindex: true, pshow: true, pcreate: true, pupdate: true, pdestroy: true
|
|
66
|
+
}).find_or_create_by(:descriptor => descriptor_owner)
|
|
67
|
+
|
|
68
|
+
admin.powers.create_with({
|
|
69
|
+
plist: true, pindex: true, pshow: true, pcreate: true, pupdate: true, pdestroy: true
|
|
70
|
+
}).find_or_create_by(:descriptor => descriptor_admin)
|
|
71
|
+
|
|
72
|
+
limited.powers.create_with({
|
|
73
|
+
plist: true, pindex: true, pshow: true, pcreate: true, pupdate: true, pdestroy: true
|
|
74
|
+
}).find_or_create_by(:descriptor => descriptor_profile)
|
|
58
75
|
end
|
|
59
76
|
|
|
60
77
|
|
|
@@ -63,56 +80,43 @@ module AccountInitializer
|
|
|
63
80
|
|
|
64
81
|
# 01.01 LesliAdmin - Lesli administration area
|
|
65
82
|
if defined? LesliAdmin
|
|
66
|
-
if self.admin.blank?
|
|
67
|
-
self.admin = LesliAdmin::Account.new
|
|
68
|
-
self.admin.account = self
|
|
69
|
-
self.admin.save!
|
|
70
|
-
end
|
|
83
|
+
LesliAdmin::Account.create!(:account => self) if self.admin.blank?
|
|
71
84
|
end
|
|
72
85
|
|
|
73
|
-
# 03.01
|
|
74
|
-
if defined?
|
|
75
|
-
if self.
|
|
76
|
-
self.driver = LesliDriver::Account.new
|
|
77
|
-
self.driver.account = self
|
|
78
|
-
self.driver.save!
|
|
79
|
-
end
|
|
86
|
+
# 03.01 LesliCalendar - Unified calendar app
|
|
87
|
+
if defined? LesliCalendar
|
|
88
|
+
LesliCalendar::Account.create!(:account => self) if self.calendar.blank?
|
|
80
89
|
end
|
|
81
90
|
|
|
82
|
-
# 03.05
|
|
91
|
+
# 03.05 LesliLetter - Notes & Notebooks
|
|
83
92
|
if defined? LesliLetter
|
|
84
|
-
if self.letter.blank?
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
LesliLetter::Account.create!(:account => self) if self.letter.blank?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# 03.06 LesliDashboard -
|
|
97
|
+
if defined? LesliDashboard
|
|
98
|
+
LesliDashboard::Account.create!(:account => self) if self.dashboard.blank?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# 03.08 LesliBell - Notification system
|
|
102
|
+
if defined? LesliBell
|
|
103
|
+
LesliBell::Account.create!(:account => self) if self.bell.blank?
|
|
89
104
|
end
|
|
90
105
|
|
|
91
106
|
# 05.02 LesliAudit - System analytics
|
|
92
107
|
if defined? LesliAudit
|
|
93
|
-
if self.audit.blank?
|
|
94
|
-
self.audit = LesliAudit::Account.new
|
|
95
|
-
self.audit.account = self
|
|
96
|
-
self.audit.save!
|
|
97
|
-
end
|
|
108
|
+
LesliAudit::Account.create!(:account => self) if self.audit.blank?
|
|
98
109
|
end
|
|
99
110
|
|
|
100
|
-
# 07.02
|
|
101
|
-
if defined?
|
|
102
|
-
if self.
|
|
103
|
-
self.help = LesliHelp::Account.new
|
|
104
|
-
self.help.account = self
|
|
105
|
-
self.help.save!
|
|
106
|
-
end
|
|
111
|
+
# 07.02 LesliSupport - Support Ticket System
|
|
112
|
+
if defined? LesliSupport
|
|
113
|
+
LesliSupport::Account.create!(:account => self) if self.support.blank?
|
|
107
114
|
end
|
|
108
115
|
|
|
109
|
-
# 08.
|
|
116
|
+
# 08.02 LesliSecurity - Users, Privileges & Access Management
|
|
110
117
|
if defined? LesliGuard
|
|
111
|
-
if self.guard.blank?
|
|
112
|
-
self.guard = LesliGuard::Account.new
|
|
113
|
-
self.guard.account = self
|
|
114
|
-
self.guard.save!
|
|
115
|
-
end
|
|
118
|
+
LesliGuard::Account.create!(:account => self) if self.guard.blank?
|
|
116
119
|
end
|
|
120
|
+
|
|
117
121
|
end
|
|
118
122
|
end
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
=begin
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
@@ -28,6 +28,10 @@ Building a better future, one line of code at a time.
|
|
|
28
28
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
30
|
// ·
|
|
31
|
-
|
|
31
|
+
=end
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
module Lesli
|
|
34
|
+
class Account::Detail < ApplicationLesliRecord
|
|
35
|
+
belongs_to :account
|
|
36
|
+
end
|
|
37
|
+
end
|