lesli 5.0.11 → 5.0.13
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/brand/app-logo.png +0 -0
- data/app/assets/images/lesli/lesli-logo.svg +4 -0
- data/app/assets/javascripts/lesli/templates/application.js +14 -0
- data/app/assets/javascripts/lesli/templates/public.js +14 -0
- data/app/assets/stylesheets/lesli/templates/application.css +1365 -293
- data/app/assets/stylesheets/lesli/templates/public.css +1 -1
- data/app/controllers/lesli/abouts_controller.rb +12 -18
- data/app/controllers/lesli/application_controller.rb +26 -25
- data/app/controllers/lesli/application_lesli_controller.rb +5 -6
- data/app/controllers/lesli/interfaces/application/authorization.rb +2 -2
- 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 +26 -8
- data/app/helpers/lesli/navigation_helper.rb +53 -92
- data/app/lib/date2.rb +8 -0
- data/app/lib/lesli/system.rb +17 -4
- data/app/models/concerns/account_initializer.rb +46 -42
- data/app/models/concerns/user_extensions.rb +6 -0
- 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/controller_operator.rb +4 -1
- data/app/operators/lesli/user_registration_operator.rb +3 -3
- data/app/services/lesli/user_service.rb +1 -1
- data/app/views/lesli/layouts/application-devise.html.erb +6 -6
- data/app/views/lesli/layouts/application-lesli.html.erb +3 -1
- data/app/views/lesli/partials/_application-data.html.erb +5 -4
- data/app/views/lesli/partials/_application-lesli-engines.html.erb +14 -39
- data/app/views/lesli/partials/_application-lesli-header.html.erb +50 -25
- data/app/views/lesli/partials/_application-lesli-icons.html.erb +1 -1
- data/app/views/lesli/partials/_application-lesli-javascript.html.erb +2 -2
- data/app/views/lesli/partials/_application-lesli-navigation.html.erb +8 -1
- data/app/views/lesli/partials/_application-lesli-panels.html.erb +7 -7
- data/app/views/lesli/partials/_application-lesli-scss.html.erb +2 -2
- data/app/views/lesli/wrappers/_application-devise-simple.erb +1 -1
- data/app/views/lesli/wrappers/_application-devise.html.erb +5 -7
- data/config/initializers/devise.rb +335 -335
- data/config/initializers/lesli.rb +9 -2
- data/config/locales/translations.en.yml +9 -3
- data/config/locales/translations.es.yml +9 -3
- data/config/locales/translations.fr.yml +30 -0
- data/config/locales/translations.it.yml +30 -0
- data/config/locales/translations.pt.yml +30 -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/generators/application_lesli_generator.rb +164 -0
- data/lib/generators/lesli/spec/USAGE +8 -0
- data/lib/generators/lesli/spec/spec_generator.rb +25 -0
- data/lib/generators/lesli/spec/templates/spec-factory.template +17 -0
- data/lib/generators/lesli/spec/templates/spec-model.template +70 -0
- data/lib/lesli/configuration.rb +1 -1
- data/lib/lesli/engine.rb +3 -14
- data/lib/{scss/devise/passwords.scss → lesli/r_spec.rb} +12 -5
- data/lib/lesli/routing.rb +51 -20
- data/lib/lesli/version.rb +2 -2
- data/lib/lesli.rb +1 -0
- data/lib/scss/cloud-objects/discussion.scss +8 -5
- data/lib/scss/layouts/application-component.scss +1 -1
- data/lib/scss/{devise/sessions.scss → layouts/application-content.scss} +4 -4
- data/lib/scss/layouts/application-header.scss +38 -108
- data/lib/scss/layouts/{application-navbar.scss → application-navigation.scss} +23 -5
- data/lib/scss/layouts/application-search.scss +1 -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/settings/variables.scss +1 -1
- data/lib/scss/templates/application.scss +14 -41
- data/lib/scss/templates/public.scss +6 -4
- data/lib/tasks/lesli/controllers.rake +1 -1
- data/lib/tasks/lesli/db.rake +24 -12
- data/lib/tasks/lesli_tasks.rake +7 -7
- data/lib/vue/application.js +18 -15
- 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-component.vue +2 -2
- data/lib/vue/layouts/application-header.vue +109 -88
- data/lib/vue/panels/{panel-notifications.vue → panel-bell-notifications.vue} +15 -19
- data/lib/vue/panels/panel-support-tickets.vue +163 -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 +119 -2
- data/lib/webpack/base.js +18 -12
- data/lib/webpack/core.js +16 -12
- data/lib/webpack/engines.js +3 -1
- data/lib/webpack/root.js +105 -0
- data/lib/webpack/version.js +37 -0
- data/readme.md +16 -15
- metadata +58 -92
- data/app/assets/icons/lesli/engine-guard.svg +0 -1
- data/app/assets/javascripts/lesli/users/sessions.js +0 -1
- data/app/assets/stylesheets/lesli/users/sessions.css +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/scss/bulma/loader.scss +0 -92
- data/lib/scss/components/editor-richtext.scss +0 -88
- data/lib/scss/devise/oauth.scss +0 -34
- 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
|
+
|
|
@@ -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
|
|
@@ -39,30 +39,48 @@ module Lesli
|
|
|
39
39
|
# lesli_application_stylesheet_path(:engine) (TODO) -> stylesheet from engine current
|
|
40
40
|
# lesli_application_stylesheet_path(:cloud_driver) -> stylesheet from engine specific
|
|
41
41
|
def lesli_application_stylesheet_path(engine = nil)
|
|
42
|
+
|
|
43
|
+
# Stylesheets from specific engine
|
|
42
44
|
return "#{engine}/templates/application" if engine
|
|
43
45
|
|
|
44
|
-
|
|
46
|
+
# Get current engine information
|
|
47
|
+
lesli_engine_code = lesli_engine(:code)
|
|
48
|
+
|
|
49
|
+
# Rails main host app stylesheets
|
|
50
|
+
return "application" if lesli_engine_code == "root"
|
|
51
|
+
|
|
52
|
+
# Rails engines stylesheets
|
|
53
|
+
"#{lesli_engine_code}/application"
|
|
45
54
|
end
|
|
46
55
|
|
|
47
56
|
# Return a string path to load the main engine stylesheet
|
|
48
57
|
def application_stylesheet_engine_path
|
|
49
|
-
|
|
58
|
+
lesli_engine = lesli_engine(:code)
|
|
50
59
|
return "administration/application" if is_lesli_administration?
|
|
51
60
|
return "onboardings/application" if is_lesli_onboarding?
|
|
52
61
|
|
|
53
|
-
"#{
|
|
62
|
+
"#{lesli_engine}/application"
|
|
54
63
|
end
|
|
55
64
|
|
|
56
65
|
# Return a string path to load the main javascript app of the engine
|
|
57
66
|
def lesli_application_javascript_path
|
|
58
67
|
# get the namespace to load specific javascript file
|
|
59
68
|
# for engine or specific javascript file for core controller
|
|
60
|
-
path_segments = controller_path.split("/")
|
|
61
|
-
|
|
69
|
+
# path_segments = controller_path.split("/")
|
|
70
|
+
# lesli_engine = path_segments.shift
|
|
62
71
|
|
|
63
|
-
return "onboardings/application" if is_lesli_onboarding?
|
|
72
|
+
# return "onboardings/application" if is_lesli_onboarding?
|
|
73
|
+
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
# Get current engine information
|
|
77
|
+
lesli_engine_code = lesli_engine(:code)
|
|
78
|
+
|
|
79
|
+
# Rails main host app stylesheets
|
|
80
|
+
return "application" if lesli_engine_code == "root"
|
|
64
81
|
|
|
65
|
-
|
|
82
|
+
# Rails engines stylesheets
|
|
83
|
+
"#{lesli_engine_code}/application"
|
|
66
84
|
end
|
|
67
85
|
|
|
68
86
|
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
|
|
@@ -42,9 +42,15 @@ module Lesli
|
|
|
42
42
|
|
|
43
43
|
# Prints a html link inside a list item
|
|
44
44
|
def navigation_item(path, label, icon = nil, reload: false)
|
|
45
|
+
content_tag(:li) do
|
|
46
|
+
navigation_link(path, label, icon, reload:reload)
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def navigation_link(path, label, icon = nil, reload: false)
|
|
45
51
|
# default vue router links for single page applications
|
|
46
52
|
html_element = "router-link"
|
|
47
|
-
html_options = { to: path }
|
|
53
|
+
html_options = { to: path, class: "navbar-item", 'active-class': "navigation-link-active" }
|
|
48
54
|
|
|
49
55
|
# if reload is nedeed, we use a standard "a" tag
|
|
50
56
|
if reload
|
|
@@ -52,148 +58,106 @@ module Lesli
|
|
|
52
58
|
html_options = { href: path }
|
|
53
59
|
end
|
|
54
60
|
|
|
55
|
-
content_tag(
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
concat content_tag(:span, label, class: "text")
|
|
64
|
-
end
|
|
61
|
+
content_tag(html_element, html_options) do
|
|
62
|
+
# print a simple menu item (without icon)
|
|
63
|
+
concat content_tag(:span, label, class: "text iconless") unless icon
|
|
64
|
+
|
|
65
|
+
# print a full menu item if icon was requested
|
|
66
|
+
if icon
|
|
67
|
+
concat content_tag(:span, nil, class: icon)
|
|
68
|
+
concat content_tag(:span, label, class: "text")
|
|
65
69
|
end
|
|
66
70
|
end
|
|
67
71
|
end
|
|
68
72
|
|
|
69
|
-
#
|
|
70
|
-
|
|
73
|
+
# ADMINISTRATION
|
|
74
|
+
|
|
75
|
+
# 01.01 Admin engine
|
|
76
|
+
def navigation_engine_admin(title: "Administration", subtitle: "Administration area.")
|
|
71
77
|
return unless defined? LesliAdmin
|
|
72
|
-
navigation_engine_item(title,
|
|
78
|
+
navigation_engine_item(title,subtitle,"admin",lesli_admin.root_path,controller_path.include?("lesli_admin"))
|
|
73
79
|
end
|
|
74
80
|
|
|
75
|
-
#
|
|
76
|
-
|
|
77
|
-
# 01.01 Team engine
|
|
81
|
+
# 01.02 Team engine
|
|
78
82
|
def navigation_engine_team(title: "Team", subtitle: "Human Resources Management")
|
|
79
83
|
return unless defined? CloudTeam
|
|
80
|
-
|
|
81
|
-
navigation_engine_item(title, subtitle, "team", cloud_team.root_path,
|
|
82
|
-
controller_path.include?("cloud_team"))
|
|
84
|
+
navigation_engine_item(title,subtitle,"team",cloud_team.root_path,controller_path.include?("cloud_team"))
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
# SALES & MARKETING
|
|
86
88
|
|
|
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
89
|
# 02.04 House engine
|
|
96
90
|
def navigation_engine_house(title: "House", subtitle: "cloud_house/house-logo.svg")
|
|
97
91
|
return unless defined? CloudHouse
|
|
98
|
-
|
|
99
|
-
navigation_engine_item(title, subtitle, "house", cloud_house.root_path,
|
|
100
|
-
controller_path.include?("cloud_house"))
|
|
92
|
+
navigation_engine_item(title,subtitle,"house",cloud_house.root_path,controller_path.include?("cloud_house"))
|
|
101
93
|
end
|
|
102
94
|
|
|
103
95
|
# 02.05 Mailer engine
|
|
104
96
|
def navigation_engine_mailer(title: "Mailer", subtitle: "Email automation system")
|
|
105
97
|
return unless defined? CloudMailer
|
|
106
|
-
|
|
107
|
-
navigation_engine_item(title, subtitle, "mailer", cloud_mailer.root_path,
|
|
108
|
-
controller_path.include?("cloud_mailer"))
|
|
98
|
+
navigation_engine_item(title,subtitle,"mailer",cloud_mailer.root_path,controller_path.include?("cloud_mailer"))
|
|
109
99
|
end
|
|
110
100
|
|
|
111
101
|
# 02.08 Proposal engine
|
|
112
102
|
def navigation_engine_proposal(title: "Proposal", subtitle: "cloud_proposal/proposal-logo.svg")
|
|
113
103
|
return unless defined? CloudProposal
|
|
114
|
-
|
|
115
|
-
navigation_engine_item(title, subtitle, "proposal", cloud_proposal.root_path,
|
|
116
|
-
controller_path.include?("cloud_proposal"))
|
|
104
|
+
navigation_engine_item(title,subtitle,"proposal",cloud_proposal.root_path,controller_path.include?("cloud_proposal"))
|
|
117
105
|
end
|
|
118
106
|
|
|
119
107
|
# PRODUCTIVITY & TEAMWORK
|
|
120
108
|
|
|
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"))
|
|
109
|
+
# 03.01 Calendar engine
|
|
110
|
+
def navigation_engine_calendar(title: "Calendar", subtitle: "Unified calendar app")
|
|
111
|
+
return unless defined? LesliCalendar
|
|
112
|
+
navigation_engine_item(title, subtitle, "calendar", lesli_calendar.root_path, controller_path.include?("lesli_calendar"))
|
|
133
113
|
end
|
|
134
114
|
|
|
135
115
|
# 03.03 Focus engine
|
|
136
116
|
def navigation_engine_focus(title: "Tasks", subtitle: "Task Management")
|
|
137
117
|
return unless defined? CloudFocus
|
|
138
|
-
|
|
139
|
-
navigation_engine_item(title, subtitle, "focus", cloud_focus.root_path,
|
|
140
|
-
controller_path.include?("cloud_focus"))
|
|
118
|
+
navigation_engine_item(title,subtitle,"focus",cloud_focus.root_path,controller_path.include?("cloud_focus"))
|
|
141
119
|
end
|
|
142
120
|
|
|
143
121
|
# 03.05 Letter engine
|
|
144
122
|
def navigation_engine_letter(title: "Letter", subtitle: "Notes & Notebooks")
|
|
145
123
|
return unless defined? LesliLetter
|
|
146
|
-
|
|
147
|
-
navigation_engine_item(title, subtitle, "letter", lesli_letter.root_path,
|
|
148
|
-
controller_path.include?("lesli_letter"))
|
|
124
|
+
navigation_engine_item(title,subtitle,"letter",lesli_letter.root_path,controller_path.include?("lesli_letter"))
|
|
149
125
|
end
|
|
150
126
|
|
|
151
127
|
# 03.06 Dashboard engine
|
|
152
128
|
def navigation_engine_dashboard(title: "Dashboard", subtitle: "Smart business assistant")
|
|
153
129
|
return unless defined? LesliDashboard
|
|
154
|
-
|
|
155
|
-
navigation_engine_item(title, subtitle, "dashboard", lesli_dashboard.root_path,
|
|
156
|
-
controller_path.include?("lesli_dashboard"))
|
|
130
|
+
navigation_engine_item(title,subtitle,"dashboard",lesli_dashboard.root_path,controller_path.include?("lesli_dashboard"))
|
|
157
131
|
end
|
|
158
132
|
|
|
159
133
|
# 03.07 Social engine
|
|
160
134
|
def navigation_engine_social(title: "Social", subtitle: "Team social network")
|
|
161
135
|
return unless defined? CloudSocial
|
|
162
|
-
|
|
163
|
-
navigation_engine_item(title, subtitle, "social", cloud_social.root_path,
|
|
164
|
-
controller_path.include?("cloud_social"))
|
|
136
|
+
navigation_engine_item(title,subtitle,"social",cloud_social.root_path,controller_path.include?("cloud_social"))
|
|
165
137
|
end
|
|
166
138
|
|
|
167
139
|
# 03.08 Bell engine
|
|
168
|
-
def navigation_engine_bell(title: "Notifications", subtitle: "
|
|
140
|
+
def navigation_engine_bell(title: "Notifications", subtitle: "Notifications & Announcements")
|
|
169
141
|
return unless defined? LesliBell
|
|
170
|
-
|
|
171
|
-
navigation_engine_item(title, subtitle, "bell", lesli_bell.root_path,
|
|
172
|
-
controller_path.include?("lesli_bell"))
|
|
142
|
+
navigation_engine_item(title, subtitle, "bell", lesli_bell.root_path, controller_path.include?("lesli_bell"))
|
|
173
143
|
end
|
|
174
144
|
|
|
175
145
|
# 03.09 Time engine
|
|
176
146
|
def navigation_engine_time(title: "Time managment", subtitle: "Track your time")
|
|
177
147
|
return unless defined? CloudTime
|
|
178
|
-
|
|
179
|
-
navigation_engine_item(title, subtitle, "time", cloud_time.root_path,
|
|
180
|
-
controller_path.include?("cloud_time"))
|
|
148
|
+
navigation_engine_item(title,subtitle,"time",cloud_time.root_path,controller_path.include?("cloud_time"))
|
|
181
149
|
end
|
|
182
150
|
|
|
183
151
|
# 03.10 Talk engine
|
|
184
152
|
def navigation_engine_talk(title: "Talk", subtitle: "Real-time communication")
|
|
185
153
|
return unless defined? CloudTalk
|
|
186
|
-
|
|
187
|
-
navigation_engine_item(title, subtitle, "talk", cloud_talk.root_path,
|
|
188
|
-
controller_path.include?("cloud_talk"))
|
|
154
|
+
navigation_engine_item(title,subtitle,"talk",cloud_talk.root_path,controller_path.include?("cloud_talk"))
|
|
189
155
|
end
|
|
190
156
|
|
|
191
157
|
# 03.11 Storage engine
|
|
192
158
|
def navigation_engine_storage(title: "Storage", subtitle: "Cloud files management")
|
|
193
159
|
return unless defined? CloudStorage
|
|
194
|
-
|
|
195
|
-
navigation_engine_item(title, subtitle, "storage", cloud_storage.root_path,
|
|
196
|
-
controller_path.include?("cloud_storage"))
|
|
160
|
+
navigation_engine_item(title,subtitle,"storage",cloud_storage.root_path,controller_path.include?("cloud_storage"))
|
|
197
161
|
end
|
|
198
162
|
|
|
199
163
|
# FINANCE
|
|
@@ -224,14 +188,13 @@ module Lesli
|
|
|
224
188
|
|
|
225
189
|
# ANALYTICS
|
|
226
190
|
|
|
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"))
|
|
191
|
+
# 05.02 Audit engine
|
|
192
|
+
def navigation_engine_audit(title: "Audit", subtitle: "Activity, logs, security and more")
|
|
193
|
+
return unless defined? LesliAudit
|
|
194
|
+
navigation_engine_item(title, subtitle, "audit", lesli_audit.root_path, controller_path.include?("lesli_audit"))
|
|
233
195
|
end
|
|
234
196
|
|
|
197
|
+
|
|
235
198
|
# INTELLIGENCE
|
|
236
199
|
|
|
237
200
|
# 06.06 Scraper engine
|
|
@@ -277,21 +240,19 @@ module Lesli
|
|
|
277
240
|
|
|
278
241
|
# SECURITY & PRIVACY
|
|
279
242
|
|
|
280
|
-
# 08.01
|
|
281
|
-
def
|
|
282
|
-
return unless defined?
|
|
283
|
-
navigation_engine_item(title, subtitle, "
|
|
284
|
-
controller_path.include?("lesli_guard"))
|
|
243
|
+
# 08.01 Shield engine
|
|
244
|
+
def navigation_engine_shield(title: "Shield", subtitle: "Authentication & Authorization.")
|
|
245
|
+
return unless defined? LesliShield
|
|
246
|
+
navigation_engine_item(title, subtitle, "shield", lesli_shield.root_path, controller_path.include?("lesli_shield"))
|
|
285
247
|
end
|
|
286
248
|
|
|
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"))
|
|
249
|
+
# 08.02 Security engine
|
|
250
|
+
def navigation_engine_security(title: "Security", subtitle: "Users, Privileges & Access Management.")
|
|
251
|
+
return unless defined? LesliSecurity
|
|
252
|
+
navigation_engine_item(title, subtitle, "security", lesli_security.root_path, controller_path.include?("lesli_security"))
|
|
293
253
|
end
|
|
294
254
|
|
|
255
|
+
|
|
295
256
|
# INTEGRATIONS
|
|
296
257
|
|
|
297
258
|
# 09.01 Babel engine
|
data/app/lib/date2.rb
CHANGED
|
@@ -138,6 +138,11 @@ class Date2
|
|
|
138
138
|
# get right format for dates
|
|
139
139
|
format = self.db_format
|
|
140
140
|
|
|
141
|
+
# compatibility for SQLite
|
|
142
|
+
if ActiveRecord::Base.connection.adapter_name == "SQLite"
|
|
143
|
+
return "strftime('#{format}', #{table}#{column}) as #{column}_string"
|
|
144
|
+
end
|
|
145
|
+
|
|
141
146
|
"TO_CHAR(#{table}#{column} at time zone 'utc' at time zone '#{@settings[:time_zone]}', '#{format}') as #{column}_string"
|
|
142
147
|
|
|
143
148
|
end
|
|
@@ -175,6 +180,9 @@ class Date2
|
|
|
175
180
|
def db_format
|
|
176
181
|
format = @format
|
|
177
182
|
|
|
183
|
+
# SQLite format dates are the same of ruby format
|
|
184
|
+
return format if ActiveRecord::Base.connection.adapter_name == "SQLite"
|
|
185
|
+
|
|
178
186
|
# Convert Ruby to postgresql date format
|
|
179
187
|
format = format.gsub("%Y", "YYYY")
|
|
180
188
|
format = format.gsub("%m", "MM")
|
data/app/lib/lesli/system.rb
CHANGED
|
@@ -42,6 +42,9 @@ module Lesli
|
|
|
42
42
|
|
|
43
43
|
engines() if ENGINES.empty?
|
|
44
44
|
|
|
45
|
+
# the Root engine represents the host Rails app
|
|
46
|
+
engine = "Root" unless LESLI_ENGINES.include?(engine)
|
|
47
|
+
|
|
45
48
|
# return specific property if requested
|
|
46
49
|
return ENGINES[engine][property.to_sym] unless property.blank?
|
|
47
50
|
|
|
@@ -59,7 +62,7 @@ module Lesli
|
|
|
59
62
|
LESLI_ENGINES.each do |engine|
|
|
60
63
|
next unless Object.const_defined?(engine)
|
|
61
64
|
engine_instance = "#{engine}".constantize
|
|
62
|
-
ENGINES[engine]= {
|
|
65
|
+
ENGINES[engine] = {
|
|
63
66
|
:code => engine.underscore,
|
|
64
67
|
:name => lesli_engine_name(engine),
|
|
65
68
|
:path => engine_instance::Engine.routes.find_script_name({}),
|
|
@@ -69,6 +72,15 @@ module Lesli
|
|
|
69
72
|
}
|
|
70
73
|
end
|
|
71
74
|
|
|
75
|
+
ENGINES["Root"] = {
|
|
76
|
+
:code => "root",
|
|
77
|
+
:name => "Root",
|
|
78
|
+
:path => "/",
|
|
79
|
+
:version => "1.0.0",
|
|
80
|
+
:build => "0000000",
|
|
81
|
+
:dir => Rails.root.to_s
|
|
82
|
+
}
|
|
83
|
+
|
|
72
84
|
ENGINES
|
|
73
85
|
end
|
|
74
86
|
|
|
@@ -83,14 +95,15 @@ module Lesli
|
|
|
83
95
|
|
|
84
96
|
LESLI_ENGINES = [
|
|
85
97
|
"Lesli",
|
|
98
|
+
"LesliBell",
|
|
86
99
|
"LesliAdmin",
|
|
87
100
|
"LesliBabel",
|
|
88
101
|
"LesliAudit",
|
|
89
|
-
"
|
|
90
|
-
"LesliDriver",
|
|
91
|
-
"LesliGuard",
|
|
102
|
+
"LesliShield",
|
|
92
103
|
"LesliLetter",
|
|
93
104
|
"LesliSupport",
|
|
105
|
+
"LesliSecurity",
|
|
106
|
+
"LesliCalendar",
|
|
94
107
|
"LesliDashboard"
|
|
95
108
|
]
|
|
96
109
|
end
|