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.
Files changed (152) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/lesli_manifest.js +0 -13
  3. data/app/assets/icons/lesli/engine-security.svg +1 -0
  4. data/app/assets/icons/lesli/engine-shield.svg +1 -0
  5. data/app/assets/images/lesli/lesli-logo.svg +4 -0
  6. data/app/assets/stylesheets/lesli/templates/application.css +21862 -209
  7. data/app/assets/stylesheets/lesli/templates/public.css +19098 -1
  8. data/app/assets/stylesheets/lesli/users/confirmations.css +19219 -0
  9. data/app/assets/stylesheets/lesli/users/passwords.css +19202 -0
  10. data/app/assets/stylesheets/lesli/users/registrations.css +19594 -0
  11. data/app/assets/stylesheets/lesli/users/sessions.css +19594 -1
  12. data/app/controllers/lesli/abouts_controller.rb +12 -18
  13. data/app/controllers/lesli/application_controller.rb +25 -25
  14. data/app/controllers/lesli/application_lesli_controller.rb +5 -6
  15. data/app/controllers/lesli/interfaces/application/authorization.rb +1 -1
  16. data/app/controllers/lesli/interfaces/application/customization.rb +1 -1
  17. data/app/controllers/lesli/interfaces/application/requester.rb +2 -2
  18. data/app/controllers/lesli/interfaces/application/responder.rb +8 -8
  19. data/app/controllers/lesli/interfaces/controllers/actions.rb +250 -0
  20. data/app/controllers/lesli/interfaces/controllers/activities.rb +215 -0
  21. data/app/controllers/lesli/interfaces/controllers/discussions.rb +270 -0
  22. data/app/controllers/lesli/interfaces/controllers/files.rb +467 -0
  23. data/app/controllers/lesli/interfaces/controllers/subscribers.rb +234 -0
  24. data/app/helpers/lesli/assets_helper.rb +4 -4
  25. data/app/helpers/lesli/navigation_helper.rb +38 -81
  26. data/app/lib/lesli/system.rb +4 -3
  27. data/app/models/concerns/account_initializer.rb +46 -42
  28. data/{lib/scss/devise/registrations.scss → app/models/lesli/account/detail.rb} +7 -3
  29. data/app/models/lesli/account.rb +12 -5
  30. data/app/models/lesli/cloud_object/action.rb +70 -0
  31. data/app/models/lesli/cloud_object/activity.rb +311 -0
  32. data/app/models/lesli/cloud_object/custom_field.rb +158 -0
  33. data/app/models/lesli/cloud_object/discussion.rb +219 -0
  34. data/app/models/lesli/cloud_object/subscriber.rb +186 -0
  35. data/app/models/lesli/shared/dashboard.rb +16 -5
  36. data/app/models/lesli/user/session.rb +0 -2
  37. data/app/models/lesli/user.rb +13 -13
  38. data/app/operators/lesli/user_registration_operator.rb +3 -3
  39. data/app/views/lesli/layouts/application-devise.html.erb +6 -6
  40. data/app/views/lesli/layouts/application-lesli.html.erb +1 -1
  41. data/app/views/lesli/partials/_application-data.html.erb +2 -1
  42. data/app/views/lesli/partials/_application-lesli-engines.html.erb +14 -39
  43. data/app/views/lesli/partials/_application-lesli-header.html.erb +4 -4
  44. data/app/views/lesli/partials/_application-lesli-icons.html.erb +1 -1
  45. data/app/views/lesli/partials/_application-lesli-panels.html.erb +7 -7
  46. data/app/views/lesli/wrappers/_application-devise.html.erb +5 -7
  47. data/config/initializers/devise.rb +335 -335
  48. data/config/initializers/lesli.rb +2 -1
  49. data/config/locales/translations.en.yml +4 -0
  50. data/config/locales/translations.es.yml +4 -0
  51. data/config/locales/translations.fr.yml +28 -0
  52. data/config/locales/translations.it.yml +28 -0
  53. data/config/locales/translations.pt.yml +28 -0
  54. data/config/routes.rb +1 -10
  55. data/db/migrate/{v1.0/0010003010_create_lesli_user_details.rb → v1/0010000110_create_lesli_accounts.rb} +19 -13
  56. data/db/migrate/{v1.0/0010000110_create_lesli_accounts.rb → v1/0010001010_create_lesli_account_details.rb} +5 -7
  57. data/db/migrate/{v1.0/0010001010_create_lesli_account_settings.rb → v1/0010001110_create_lesli_account_settings.rb} +2 -2
  58. data/db/seed/development/accounts.rb +10 -7
  59. data/db/seed/development/users.rb +20 -20
  60. data/db/seed/production/accounts.rb +10 -7
  61. data/lib/lesli/engine.rb +2 -12
  62. data/lib/lesli/version.rb +2 -2
  63. data/lib/lesli.rb +0 -1
  64. data/lib/scss/cloud-objects/discussion.scss +8 -5
  65. data/lib/scss/layouts/application-header.scss +3 -1
  66. data/lib/scss/layouts/application-navbar.scss +2 -1
  67. data/lib/scss/{elements/msg.scss → overrides/notification.scss} +16 -18
  68. data/lib/scss/pages/devise-simple.scss +4 -2
  69. data/lib/scss/pages/devise.scss +111 -107
  70. data/lib/scss/panels/panel-notification.scss +1 -1
  71. data/lib/scss/panels/{panel-ticket.scss → panel-support-ticket.scss} +3 -4
  72. data/lib/scss/templates/application.scss +7 -5
  73. data/lib/tasks/lesli/controllers.rake +1 -1
  74. data/lib/tasks/lesli/db.rake +24 -12
  75. data/lib/tasks/lesli_tasks.rake +6 -6
  76. data/lib/vue/application.js +13 -12
  77. data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/content.vue +10 -8
  78. data/lib/vue/cloudobjects/discussion/element.vue +170 -0
  79. data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/filters.vue +1 -1
  80. data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/new.vue +20 -16
  81. data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion.vue +25 -24
  82. data/lib/vue/{refactor/stores/cloudobjects → cloudobjects/stores}/discussion.js +7 -16
  83. data/lib/vue/layouts/application-header.vue +5 -5
  84. data/lib/vue/panels/{panel-notifications.vue → panel-bell-notifications.vue} +15 -19
  85. data/lib/vue/panels/panel-support-tickets.vue +161 -0
  86. data/lib/vue/panels/stores/bell-notifications.js +46 -0
  87. data/lib/vue/panels/stores/support-tickets.js +103 -0
  88. data/lib/vue/shared/dashboards/apps/edit.vue +10 -10
  89. data/lib/vue/shared/dashboards/components/form.vue +31 -40
  90. data/lib/vue/shared/stores/dashboard.js +2 -0
  91. data/lib/vue/shared/stores/layout.js +2 -1
  92. data/lib/{scss/devise/confirmations.scss → vue/shared/stores/users.js} +22 -21
  93. data/lib/vue/stores/translations.json +109 -2
  94. data/lib/webpack/base.js +9 -8
  95. data/lib/webpack/core.js +8 -6
  96. data/readme.md +16 -15
  97. metadata +49 -76
  98. data/app/assets/icons/lesli/engine-guard.svg +0 -1
  99. data/app/assets/javascripts/lesli/users/sessions.js +0 -1
  100. data/app/controllers/users/confirmations_controller.rb +0 -66
  101. data/app/controllers/users/omniauth_callbacks_controller.rb +0 -30
  102. data/app/controllers/users/passwords_controller.rb +0 -71
  103. data/app/controllers/users/registrations_controller.rb +0 -141
  104. data/app/controllers/users/sessions_controller.rb +0 -141
  105. data/app/controllers/users/unlocks_controller.rb +0 -30
  106. data/app/views/devise/confirmations/new.html.erb +0 -2
  107. data/app/views/devise/confirmations/show.html.erb +0 -63
  108. data/app/views/devise/mailer/confirmation_instructions.html.erb +0 -5
  109. data/app/views/devise/mailer/email_changed.html.erb +0 -7
  110. data/app/views/devise/mailer/password_change.html.erb +0 -3
  111. data/app/views/devise/mailer/reset_password_instructions.html.erb +0 -8
  112. data/app/views/devise/mailer/unlock_instructions.html.erb +0 -7
  113. data/app/views/devise/passwords/edit.html.erb +0 -79
  114. data/app/views/devise/passwords/new.html.erb +0 -75
  115. data/app/views/devise/registrations/edit.html.erb +0 -43
  116. data/app/views/devise/registrations/new.html.erb +0 -147
  117. data/app/views/devise/sessions/new.html.erb +0 -114
  118. data/app/views/devise/shared/_demo.html.erb +0 -7
  119. data/app/views/devise/shared/_error_messages.html.erb +0 -15
  120. data/app/views/devise/shared/_links.html.erb +0 -96
  121. data/app/views/devise/unlocks/new.html.erb +0 -16
  122. data/db/migrate/v1.0/0010000210_create_lesli_roles.rb +0 -59
  123. data/db/migrate/v1.0/0010000310_create_lesli_users.rb +0 -97
  124. data/db/migrate/v1.0/0010003110_create_lesli_user_settings.rb +0 -44
  125. data/db/migrate/v1.0/0010003210_create_lesli_user_sessions.rb +0 -55
  126. data/db/migrate/v1.0/0010003410_create_lesli_user_powers.rb +0 -43
  127. data/db/migrate/v1.0/0010004010_create_lesli_user_logs.rb +0 -45
  128. data/db/migrate/v1.0/0010005010_create_lesli_descriptors.rb +0 -44
  129. data/db/migrate/v1.0/0010005110_create_lesli_descriptor_privileges.rb +0 -45
  130. data/db/migrate/v1.0/0010005210_create_lesli_descriptor_activities.rb +0 -49
  131. data/db/migrate/v1.0/0010005510_create_lesli_role_powers.rb +0 -51
  132. data/db/migrate/v1.0/0010005710_create_lesli_role_privileges.rb +0 -45
  133. data/lib/lesli/routing.rb +0 -26
  134. data/lib/scss/components/editor-richtext.scss +0 -88
  135. data/lib/scss/devise/oauth.scss +0 -34
  136. data/lib/scss/devise/passwords.scss +0 -33
  137. data/lib/scss/devise/sessions.scss +0 -35
  138. data/lib/scss/elements/avatar.scss +0 -48
  139. data/lib/scss/elements/calendar.scss +0 -47
  140. data/lib/scss/elements/toggle.scss +0 -102
  141. data/lib/vue/devise/confirmations.js +0 -33
  142. data/lib/vue/devise/passwords.js +0 -137
  143. data/lib/vue/devise/registrations.js +0 -157
  144. data/lib/vue/devise/sessions.js +0 -148
  145. data/lib/vue/panels/panel-tickets.vue +0 -181
  146. data/lib/vue/refactor/shared/cloudobjects/discussion/element.vue +0 -132
  147. data/lib/vue/shared/stores/account.js +0 -113
  148. /data/app/assets/icons/lesli/{engine-driver.svg → engine-calendar.svg} +0 -0
  149. /data/db/migrate/{v1.0 → v1}/0010000610_create_lesli_system_controllers.rb +0 -0
  150. /data/db/migrate/{v1.0 → v1}/0010000710_create_lesli_system_controller_actions.rb +0 -0
  151. /data/db/migrate/{v1.0 → v1}/0010001210_create_lesli_account_activities.rb +0 -0
  152. /data/db/migrate/{v1.0 → v1}/0010001410_create_lesli_account_logs.rb +0 -0
@@ -0,0 +1,270 @@
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 · 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
32
+
33
+ module Lesli
34
+ module Interfaces
35
+ module Controllers
36
+ module Discussions
37
+
38
+ # @return [Json] Json that contains a list of all discussions related to a *cloud_object*
39
+ # @description Retrieves and returns all discussions associated to a *cloud_object*. The id of the
40
+ # *cloud_object* is within the *params* attribute. If the child class provides a block, the function is
41
+ # yielded sending the discussions as parameters. The block given *must* return the HTTP response
42
+ # @example
43
+ # # Executing this controller's action from javascript's frontend
44
+ # let ticket_id = 1;
45
+ # this.http.get(`127.0.0.1/help/tickets/${ticket_id}/discussions`);
46
+ def index
47
+ discussion_model = discussion_model() # If there is a custom discussion model, it must be returned in this method
48
+ cloud_object_model = discussion_model.cloud_object_model
49
+
50
+ @discussions = discussion_model.index(
51
+ current_user,
52
+ params["#{cloud_object_model.name.demodulize.underscore}_id".to_sym],
53
+ @query
54
+ )
55
+ if block_given?
56
+ yield(@discussions)
57
+ else
58
+ #respond_with_successful(@discussions)
59
+ respond_with_pagination(@discussions)
60
+ end
61
+ end
62
+
63
+ # @return [JSON] The json information about the selected discussion
64
+ # @description Retrieves and returns the information about the discussion. The id of the
65
+ # *cloud_object* and the id of the *discussion* are within the *params* attribute. If a block
66
+ # is provided, the execution will be yielded sending the discussion as first parameter
67
+ # @example
68
+ # # Executing this controller's action from javascript's frontend
69
+ # let ticket_id = 1;
70
+ # let discussion_id = 5;
71
+ # this.http.get(`127.0.0.1/help/tickets/${ticket_id}/discussions/${discussion_id}`);
72
+ def show
73
+ set_discussion
74
+ return respond_with_not_found unless @discussion
75
+
76
+ if block_given?
77
+ yield(@discussion)
78
+ else
79
+ return respond_with_successful(@discussion)
80
+ end
81
+ end
82
+
83
+ # @controller_action_param :content [String] The commented message
84
+ # @controller_action_param :discussions_id [Integer] The id of a discussions that this message responds to
85
+ # @return [Json] Json that contains wheter the creation of the discussion was successful or not.
86
+ # If it is not successful, it returs an error message
87
+ # @description Creates a new discussion associated to a *cloud_object* and notifies all users subscribed to this event.
88
+ # The id of the *cloud_object* is within the *params* attribute
89
+ # @example
90
+ # # Executing this controller's action from javascript's frontend
91
+ # let ticket_id = 1;
92
+ # let data = {
93
+ # ticket_discussion: {
94
+ # content: "This is a comment on a ticket!"
95
+ # }
96
+ # };
97
+ # this.http.post(`127.0.0.1/help/tickets/${ticket_id}/discussions`, data);
98
+ def create
99
+ discussion_model = discussion_model() # If there is a custom discussion model, it must be returned in this method
100
+ cloud_object_model = discussion_model.cloud_object_model
101
+
102
+ set_cloud_object
103
+ new_discussion_params = {
104
+ #"#{discussion_model.table_name}_id": discussion_params[:discussion_parent_id],
105
+ content: discussion_params[:content],
106
+ user_creator: current_user,
107
+ cloud_object: @cloud_object
108
+ }
109
+
110
+
111
+ discussion = discussion_model.new(new_discussion_params)
112
+ if discussion.save
113
+ translations_path = @cloud_object.class.name.gsub("Cloud", "").underscore.pluralize.gsub("/", ".")
114
+ cloud_object_class_translation = I18n.t("#{translations_path}.view_title_main")
115
+
116
+ "#{cloud_object_model}::Subscriber".constantize.notify_subscribers(
117
+ current_user,
118
+ discussion.cloud_object,
119
+ "discussion_created",
120
+ subject: "#{cloud_object_class_translation} (#{@cloud_object.global_identifier}): #{I18n.t("core.shared.view_title_notification_discussions_created")}",
121
+ body: "#{discussion.user_creator.full_name} #{I18n.t("core.shared.view_text_notification_discussion_created_body")}: '#{discussion.content}'",
122
+ url: "/#{@cloud_object.class.name.split("::").last.pluralize.downcase}/#{@cloud_object.url_identifier}?tab=discussions"
123
+ ) if Object.const_defined?("#{cloud_object_model}::Subscriber")
124
+
125
+
126
+ if block_given?
127
+ yield(cloud_object, discussion)
128
+ else
129
+ # Returning the 200 HTTP response
130
+ respond_with_successful(discussion.show(current_user))
131
+ end
132
+ else
133
+ respond_with_error(discussion.errors.full_messages)
134
+ end
135
+ end
136
+
137
+ # @controller_action_param :content [String] The content of the discussion
138
+ # @controller_action_param :discussions_id [Integer] The id of a discussions that this message responds to
139
+ # @return [Json] Json that contains wheter the update of the discussion was successful or not.
140
+ # If it is not successful, it returs an error message
141
+ # @description Updates the discussion based on the id of the *cloud_object* and its own id.
142
+ # @example
143
+ # # Executing this controller's action from javascript's frontend
144
+ # let ticket_id = 1;
145
+ # let discussion_id = 22;
146
+ # data = {
147
+ # discussion: {
148
+ # content: "This is the new content of the discussion"
149
+ # }
150
+ # };
151
+ # this.http.patch(`127.0.0.1/help/tickets/${ticket_id}/discussions/${discussion_id}`, data);
152
+ def update
153
+ set_discussion
154
+ return respond_with_not_found unless @discussion
155
+ return respond_with_unauthorized unless @discussion.is_editable_by?(current_user)
156
+
157
+ if @discussion.update(discussion_params)
158
+ respond_with_successful
159
+ else
160
+ respond_with_error(@discussion.errors.full_messages.to_sentence)
161
+ end
162
+ end
163
+
164
+ # @return [Json] A response that contains wheter the discussion was deleted or not.
165
+ # If it is not successful, it returns an error message
166
+ # @description Deletes a discussion from the database based on the id of the *cloud_object* and its own id.
167
+ # @example
168
+ # # Executing this controller's action from javascript's frontend
169
+ # let ticket_id = 1;
170
+ # let discussion_id = 22;
171
+ # this.http.delete(`127.0.0.1/help/tickets/${ticket_id}/discussions/${discussion_id}`);
172
+ def destroy
173
+ set_discussion
174
+ return respond_with_not_found unless @discussion
175
+
176
+ if @discussion.destroy
177
+ respond_with_successful
178
+ else
179
+ respond_with_error(@discussion.errors.full_messages.to_sentence)
180
+ end
181
+ end
182
+
183
+ protected
184
+
185
+ # @return [Parameters] Allowed parameters for the discussion
186
+ # @description Sanitizes the parameters received from an HTTP call to only allow the specified ones.
187
+ # Allowed params are _:content_, _:discussions_id_.
188
+ # @example
189
+ # # supose params contains {
190
+ # # "ticket_discussion": {
191
+ # # "id": 5,
192
+ # # "content": "This is a message!",
193
+ # # "cloud_help_ticket_discussions_id": 4
194
+ # # }
195
+ # #}
196
+ # discussion_params = discussion_params
197
+ # puts discussion_params
198
+ # # will remove the _id_ field and only print {
199
+ # # "ticket_discussion": {
200
+ # # "content": "This is a message!",
201
+ # # "cloud_help_ticket_discussions_id": 4
202
+ # # }
203
+ # #}
204
+ def discussion_params
205
+ discussion_model = discussion_model() # If there is a custom discussion model, it must be returned in this method
206
+ cloud_object_model = discussion_model.cloud_object_model
207
+
208
+ params.require(
209
+ "#{cloud_object_model.name.demodulize.underscore}_discussion".to_sym
210
+ ).permit(
211
+ :discussion_id,
212
+ :content
213
+ )
214
+ end
215
+
216
+ # @return [void]
217
+ # @descriptions Sets the variable @cloud_object based on the paremeters send in the URL. If no,
218
+ # cloud_object is found or it is not within the current_user's account, nil is used instead
219
+ # @example
220
+ # # Imagine you are inside CloudFocus::Task::DiscussionsController
221
+ # puts @cloud_object # will display nil
222
+ # set_cloud_object
223
+ # puts @cloud_object # Will display an instance of CloudFocus::Task
224
+ def set_cloud_object
225
+ discussion_model = discussion_model() # If there is a custom discussion model, it must be returned in this method
226
+ cloud_object_model = discussion_model.cloud_object_model
227
+ account_model = cloud_object_model.reflect_on_association(:account).klass
228
+
229
+ @cloud_object = cloud_object_model.find_by(
230
+ id: params["#{cloud_object_model.name.demodulize.underscore}_id".to_sym],
231
+ "#{account_model.table_name}_id".to_sym => current_user.account.id
232
+ )
233
+ end
234
+
235
+ # @return [void]
236
+ # @description Sets the variable @discussion. The variable contains the discussion
237
+ # to be updated based on the id of the *cloud_object* and the id of the *discussion*
238
+ # @example
239
+ # #suppose params[:ticket_id] = 1
240
+ # #suppose params[:id] = 44
241
+ # puts @discussion # will display nil
242
+ # set_discussion
243
+ # puts @discussion # will display an instance of CloudHelp:Ticket::Discussion
244
+ def set_discussion
245
+ discussion_model = discussion_model() # If there is a custom discussion model, it must be returned in this method
246
+ cloud_object_model = discussion_model.cloud_object_model
247
+ account_model = cloud_object_model.reflect_on_association(:account).klass
248
+
249
+ @discussion = discussion_model.joins(:cloud_object).where(
250
+ "#{cloud_object_model.table_name}.id = #{params["#{cloud_object_model.name.demodulize.underscore}_id".to_sym]}",
251
+ "#{cloud_object_model.table_name}.#{account_model.table_name}_id = #{current_user.account.id}"
252
+ ).find_by(
253
+ id: params[:id]
254
+ )
255
+ end
256
+
257
+ # @return [CloudObject::Discussion] The discussion model that the controller will handle
258
+ # @descriptions Constantizes and returns the discussion model associated to this controller. This method
259
+ # can be overrided by the implementation in the child controller
260
+ # @example
261
+ # # Suppose you are inside CloudHelp::Ticket::DiscussionsController
262
+ # puts discussion_model().new
263
+ # # This will display a new instance of CloudHelp::Ticket::Discussion
264
+ def discussion_model
265
+ self.class.name.gsub("Controller","").singularize.constantize
266
+ end
267
+ end
268
+ end
269
+ end
270
+ end