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,219 @@
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
+ module Lesli
33
+ class CloudObject::Discussion < ApplicationLesliRecord
34
+ self.abstract_class = true
35
+ belongs_to :user_creator, class_name: "::User", foreign_key: "users_id"
36
+
37
+ # @return [User] This method will always return nil
38
+ # @description At the current time, this is a dummy method that returns nil, so the function is_editable_by? in
39
+ # ApplicationLesliRecord will work without issues
40
+ def user_main
41
+ return nil
42
+ end
43
+
44
+ # @param account [Account] Account from current user
45
+ # @param cloud_id [Integer] Id of the *cloud_object* to which this discussion belongs to
46
+ # @param query [Query] that contains the search and pagination information
47
+ # @return [Array] Array of discussions. Each discussion contains a *responses* element,
48
+ # which is an array that has all its responses ordered by date
49
+ # @description Retrieves and returns all discussions from a *cloud_object*,
50
+ # including information of the user that published the comment
51
+ # @example
52
+ # current_user = the user making this request
53
+ # employee_id = params[:employee_id]
54
+ # discussions = CloudTeam::Employee::Discussion.index( account, employee_id, @query )
55
+ def self.index(current_user, cloud_id, query)
56
+ cloud_object_model = self.cloud_object_model
57
+ account_model = cloud_object_model.reflect_on_association(:account).klass
58
+
59
+ # get search string from query params
60
+ #search_string = query[:search].downcase.gsub(" ","%") unless query[:search].blank?
61
+
62
+ discussions = self.joins(:cloud_object)
63
+ .joins("inner join lesli_users u on #{self.table_name}.user_id = u.id")
64
+ .where("#{cloud_object_model.table_name}.id = #{cloud_id}")
65
+ .where("#{cloud_object_model.table_name}.account_id = #{current_user.account.id}")
66
+ .select(
67
+ "#{self.table_name}.id",
68
+ "#{self.table_name}.user_id",
69
+ "#{self.table_name}.content",
70
+ Date2.new.date_time.db_timestamps("#{self.table_name}"),
71
+ "u.email",
72
+ "CONCAT_WS(' ', u.first_name, u.last_name) as user_name"
73
+ )
74
+
75
+ # Filter results by search string
76
+ # unless search_string.blank?
77
+ # discussions = discussions.where("
78
+ # (LOWER(ud.first_name) SIMILAR TO '%#{search_string}%') OR
79
+ # (LOWER(ud.last_name) SIMILAR TO '%#{search_string}%') OR
80
+ # (LOWER(#{self.table_name}.content) SIMILAR TO '%#{search_string}%')
81
+ # ")
82
+ # end
83
+
84
+ discussions = self.format_discussions(discussions)
85
+
86
+ Kaminari.paginate_array(discussions).page(query[:pagination][:page]).per(query[:pagination][:perPage])
87
+ end
88
+
89
+ # @return [Hash] Information about the discussion
90
+ # @description Retrieves and returns a specific discussion, along with information about the user
91
+ # that created it
92
+ # @example
93
+ # discussion = CloudHelp::Ticket::Discussion.first
94
+ # puts discussion.show #This will display extra information about the discussion, like the user's name
95
+ def show(current_user = nil)
96
+ discussion_attributes = attributes.merge({
97
+ editable: is_editable_by?(current_user),
98
+ email: user_creator.email,
99
+ user_name: user_creator.full_name
100
+ })
101
+ discussion_attributes["created_at"] = LC::Date.to_string_datetime(discussion_attributes["created_at"])
102
+
103
+ discussion_attributes
104
+ end
105
+
106
+ # @return [Class] The class of the association 'belongs_to'
107
+ # @description All discussions belong to a *cloud_object*. This method returns the specific class of
108
+ # that cloud_object.
109
+ # @example
110
+ # puts DeutscheLeibrenten::Project::Discussion.cloud_object_model.new # This will display an instance of DeutscheLeibrenten::Project
111
+ def self.cloud_object_model
112
+ self.reflect_on_association(:cloud_object).klass
113
+ end
114
+
115
+ private
116
+
117
+ # @param discussions [Arrray] An array of discussions that were previously filtered
118
+ # @return [Array] A new array of discussions, nesting the responses within the parent discussions
119
+ # @description Geretes a new array of discussions, nesting the responses inside the parent discussions and order them by date
120
+ # This method uses the *nest_responses* method to support the nesting action recursively
121
+ # @example
122
+ # # Imagine that discussions has 2 discussions, the first one is a normal discussion, and the second one is a response to the first one
123
+ # puts discussions # will display something like
124
+ # # [
125
+ # # {
126
+ # # id: 1,
127
+ # # users_id: 2,
128
+ # # created_at: Date(),
129
+ # # content: 'This is a root discussion',
130
+ # # user_name: 'System',
131
+ # # discussions_id: null
132
+ # # }, {
133
+ # # id: 2,
134
+ # # users_id: 2,
135
+ # # created_at: Date(),
136
+ # # content: 'This is a response',
137
+ # # user_name: 'Test',
138
+ # # discussions_id: 1
139
+ # # }
140
+ # # ]
141
+ # puts Discussion.format_discussions(discussions) # Will display something like
142
+ # # [
143
+ # # {
144
+ # # id: 1,
145
+ # # users_id: 2,
146
+ # # created_at: Date(),
147
+ # # content: 'This is a root discussion',
148
+ # # user_name: 'System',
149
+ # # discussions_id: null,
150
+ # # responses: [{
151
+ # # id: 2,
152
+ # # users_id: 2,
153
+ # # created_at: Date(),
154
+ # # content: 'This is a response',
155
+ # # response_to: 'System'
156
+ # # user_name: 'Test',
157
+ # # discussions_id: 1
158
+ # # }]
159
+ # # }
160
+ # # ]
161
+ def self.format_discussions(discussions)
162
+ data = {}
163
+ root_discussions = []
164
+
165
+ # Add all responses to that discussion
166
+ discussions.each do |discussion|
167
+ discussion_data = {
168
+ data: discussion,
169
+ responses: []
170
+ }
171
+ data[discussion["id"]] = discussion_data
172
+
173
+ if discussion["#{self.table_name}_id"].present?
174
+ parent_discussion = data[discussion["#{self.table_name}_id"]]
175
+ next unless parent_discussion
176
+
177
+ if parent_discussion[:data]["#{self.table_name}_id"].present?
178
+ discussion["response_to"] = parent_discussion[:data]["user_name"]
179
+ end
180
+ parent_discussion[:responses].push(discussion["id"])
181
+ else
182
+ root_discussions.push(discussion_data)
183
+ end
184
+ end
185
+
186
+ # Nest the responses to root discussions. A root discussion is any comment that is not a response to another comment
187
+ root_discussions.each do |discussion|
188
+ responses = []
189
+ self.nest_responses(data, discussion, responses)
190
+ discussion[:responses] = responses
191
+ end
192
+
193
+ # revert the root discussions so the most recent comments appear in the top
194
+ root_discussions.reverse
195
+ end
196
+
197
+ # @param data [Hash] Hash that contains all the discussions, the key is the id of the discussion
198
+ # @param discussion [Hash] Hash that contains the information
199
+ # @param responses [Array] Array of discussions, that are the responses to the *discussion* param.
200
+ # It should start as an empty array
201
+ # @return [void]
202
+ # @description Recursive function that checks all discussions that are actually responses of other
203
+ # discussions and adds them to their *responses* param. It adds direct responses, responses of responses, etc.
204
+ # This is a void function that modifies the *discussion* param directly
205
+ # @example
206
+ # data = {}
207
+ # CloudHelp::Ticket::Discussion.all.each do |discussion|
208
+ # data[discussion.id] = discussion
209
+ # end
210
+ # CloudHelp::Ticket::Discussion.nest_responses(data, CloudHelp::Ticket::Discussion.first, [])
211
+ def self.nest_responses(data, discussion, responses)
212
+ discussion[:responses].each do |response_id|
213
+ response = data[response_id]
214
+ responses.push(response[:data])
215
+ self.nest_responses(data, response, responses)
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,186 @@
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
+
34
+ module Lesli
35
+ class CloudObject::Subscriber < ApplicationLesliRecord
36
+ self.abstract_class = true
37
+ belongs_to :user_creator, class_name: "::User", foreign_key: "users_id"
38
+
39
+ # @return [User] This method will always return nil
40
+ # @description At the current time, this is a dummy method that returns nil, so the function is_editable_by? in
41
+ # ApplicationLesliRecord will work without issues
42
+ def user_main
43
+ return nil
44
+ end
45
+
46
+
47
+ # @attribute [Enumerable<Symbol>] action
48
+ # @return [:discussion_created, :action_created, :file_created, :activity_created, :workflow_updated, :priority_updated, :http_get, :http_post, :http_put, :http_patch, :http_update]
49
+ enum action: {
50
+ object_created: "object_created",
51
+ object_updated: "object_updated",
52
+ object_destroyed: "object_destroyed",
53
+ object_status_updated: "object_status_updated",
54
+
55
+ action_created: "action_created",
56
+ action_updated: "action_updated",
57
+ action_destroyed: "action_destroyed",
58
+
59
+ discussion_created: "discussion_created",
60
+ discussion_updated: "discussion_updated",
61
+ discussion_destroyed: "discussion_destroyed",
62
+
63
+ file_created: "file_created",
64
+ file_updated: "file_updated",
65
+ file_destroyed: "file_destroyed"
66
+ }
67
+ validates :action, presence: true, inclusion: { in: :action }
68
+
69
+
70
+ # @attribute [Enumerable<Symbol>] notification_type
71
+ # @return [:web, :email]
72
+ enum notification_type: {
73
+ email: "email", # notification sent by email only
74
+ webpush: "webpush", # notification for web interface only
75
+ mobilepush: "mobilepush", # notification for mobile only
76
+ mobiledialog: "mobiledialog", # open a dialog in the main app screen
77
+ push: "push", # webpush & mobilepush
78
+ }
79
+ validates :notification_type, presence: true, inclusion: { in: :notification_type }
80
+
81
+ # @param cloud_object [ApplicationRecord] Cloud object to which an user can subscribe to
82
+ # @param user [User] The user that is subscribing to the *cloud_ubject*
83
+ # @param action [Symbol] A valid action from this class's *action* enum to wich the *user* will be subscribed
84
+ # @param notification_type [Symbol] A valid notification_type from this class's *notification_type* enum
85
+ # @return [void]
86
+ # @description Subscribes a *user* to one or all *actions* of the *cloud_object*. If no *action* is provided, the *user*
87
+ # is subscribed to all the *actions*
88
+ # @example
89
+ # first_ticket = CloudHelp::Ticket.find( 1 )
90
+ # second_ticket = CloudHelp::Ticket.find( 2 )
91
+ # user = current_user
92
+ # CloudHelp::Ticket::Subscriber.add_subscriber( first_ticket, current_user )
93
+ # CloudHelp::Ticket::Subscriber.add_subscriber( second_ticket, current_user, :http_post, :email )
94
+ def self.add_subscriber(cloud_object, user, action=nil, notification_type= :web)
95
+
96
+ if action
97
+ return cloud_object.subscribers.create(
98
+ user_creator: user,
99
+ action: action,
100
+ notification_type: self.notification_types[notification_type]
101
+ )
102
+ end
103
+
104
+ self.actions.values.each do |action|
105
+ cloud_object.subscribers.create(
106
+ user_creator: user,
107
+ action: action,
108
+ notification_type: self.notification_types[notification_type]
109
+ )
110
+ end
111
+ end
112
+
113
+
114
+
115
+ # @param cloud_object [ApplicationRecord] Cloud object to which an user can subscribe to
116
+ # @param subject [String] The subject that will be shown in the notification
117
+ # @param action [Symbol] A valid action from this class's *action* enum
118
+ # @return [void]
119
+ # @description Notifies all the users subscribed to the *cloud_object*'s *action* using the *Courier* engine except the
120
+ # user that triggered the notification
121
+ # @example
122
+ # ticket = CloudHelp::Ticket.find( 1 )
123
+ # ClodHelp::Ticket::Subscriber.notify_subscribers(
124
+ # ticket,
125
+ # "A new comment has been added to ticket #{ticket.id}",
126
+ # :discussion_created
127
+ # )
128
+ def self.notify_subscribers(current_user, cloud_object, action, subject: nil, body: nil, url: nil)
129
+
130
+ unless cloud_object.subscribers.blank?
131
+ subscribers = cloud_object.subscribers.where(action: action)
132
+ subscribers = subscribers.where("users_id != ?", current_user.id) if current_user
133
+
134
+ subscribers.each do |subscriber|
135
+ Courier::Bell::Notification.new(
136
+ subscriber.user_main || subscriber.user_creator,
137
+ subject || action,
138
+ body: body,
139
+ url: url,
140
+ category: "info",
141
+ channel: subscriber.notification_type
142
+ )
143
+ end
144
+ end
145
+ end
146
+
147
+ # @param cloud_object [ApplicationRecord] Cloud object to which an user can subscribe to
148
+ # @param user [User] The user that is subscribing to the *cloud_object*
149
+ # @return [Array] Array of subscriptions. There is one subscription per *action*.
150
+ # @description Generates an array of subscription, Each element contains a subscription *action*,
151
+ # information about wheter the *user* is subscribed or not and, if the user is subscribed,
152
+ # the notification type of the subscription
153
+ # @example
154
+ # ticket = CloudHelp::Ticket.find( 1 )
155
+ # subscription_actions = CloudHelp::Ticket::Subscriber.subscription_actions(
156
+ # ticket,
157
+ # current_user
158
+ # )
159
+ def self.subscription_actions(cloud_object, user)
160
+ data = { }
161
+ actions = self.actions.keys
162
+ actions.each do |action|
163
+ data[action] = {
164
+ action: action,
165
+ subscribed: false,
166
+ notification_type: :email
167
+ }
168
+ end
169
+ cloud_object.subscribers.where(users_id: user.id).each do |subscriber|
170
+ data[subscriber.action][:id] = subscriber.id
171
+ data[subscriber.action][:subscribed] = true
172
+ data[subscriber.action][:notification_type] = subscriber.notification_type
173
+ end
174
+ data.values
175
+ end
176
+
177
+ # @return [Class] The class of the association 'belongs_to'
178
+ # @description All subscribers belong to a *cloud_object*. This method returns the specific class of
179
+ # that cloud_object.
180
+ # @example
181
+ # puts DeutscheLeibrenten::Project::Discussion.cloud_object_model.new # This will display an instance of DeutscheLeibrenten::Project
182
+ def self.cloud_object_model
183
+ self.reflect_on_association(:cloud_object).klass
184
+ end
185
+ end
186
+ end
@@ -52,12 +52,23 @@ module Lesli
52
52
  # # To execute this function, you must only do
53
53
  # my_account = Account.first
54
54
  # my_account.proposal = CloudProposal::Account.new
55
- def self.initialize_data(account)
56
- self.create!(
57
- account: account,
58
- name: "Default Dashboard",
55
+ def self.initialize_dashboard(modelo, account, components)
56
+
57
+ components.unshift({
58
+ name: "Engine version",
59
+ component_id: "engine-version",
60
+ layout: 2,
61
+ query_configuration: {},
62
+ custom_configuration: {}
63
+ })
64
+
65
+ modelo.create_with(
59
66
  default: true,
60
- main: false
67
+ main: false,
68
+ components_attributes: components
69
+ ).find_or_create_by!(
70
+ account: account,
71
+ name: "Default Dashboard"
61
72
  )
62
73
  end
63
74
 
@@ -30,8 +30,6 @@ Building a better future, one line of code at a time.
30
30
  // ·
31
31
  =end
32
32
 
33
- require "bcrypt"
34
-
35
33
  module Lesli
36
34
  class User::Session < ApplicationLesliRecord
37
35
  belongs_to :user
@@ -52,6 +52,7 @@ module Lesli
52
52
  has_many :sessions
53
53
  has_many :requests
54
54
  has_many :shortcuts
55
+ has_many :notifications, class_name: "LesliBell::Notification"
55
56
  has_many :activities, class_name: "User::Activity"
56
57
 
57
58
  # users can have many roles and too many privileges through the roles
@@ -62,23 +63,22 @@ module Lesli
62
63
 
63
64
 
64
65
  # devise implementation
65
- devise :database_authenticatable,
66
- :registerable,
67
- :rememberable,
68
- :recoverable,
69
- :validatable,
70
- :confirmable,
71
- :trackable
72
- #:omniauthable, omniauth_providers: [:google_oauth2, :facebook]
66
+ if defined? LesliSecurity
67
+ devise(
68
+ :database_authenticatable,
69
+ :registerable,
70
+ :rememberable,
71
+ :recoverable,
72
+ :validatable,
73
+ :confirmable,
74
+ :trackable);
75
+ #:omniauthable, omniauth_providers: [:google_oauth2, :facebook]
76
+ end
77
+
73
78
 
74
79
  # users belongs to an account only... and must have a role
75
80
  belongs_to :account, optional: true
76
81
 
77
- # user details are saved on separate table
78
- has_one :detail, inverse_of: :user, autosave: true, dependent: :destroy
79
- accepts_nested_attributes_for :detail, update_only: true
80
-
81
-
82
82
  # users belongs to an account only... and must have a role
83
83
  belongs_to :account, optional: true
84
84
 
@@ -78,9 +78,9 @@ module Lesli
78
78
  # create new account for the new user only if multi-account is allowed
79
79
  if allow_multiaccount === true
80
80
  account = Account.create!({
81
- user: resource, # set user as owner of his just created account
82
- company_name: "Lesli", # temporary company name
83
- status: :active # account is active due user already confirmed his email
81
+ user: resource, # set user as owner of his just created account
82
+ name: "Lesli", # temporary company name
83
+ status: :active # account is active due user already confirmed his email
84
84
  })
85
85
  end
86
86
 
@@ -18,9 +18,9 @@ GNU General Public License for more details.
18
18
  You should have received a copy of the GNU General Public License
19
19
  along with this program. If not, see http://www.gnu.org/licenses/.
20
20
 
21
- Lesli · Ruby on Rails SaaS development platform.
21
+ Lesli · Ruby on Rails SaaS Development Framework.
22
22
 
23
- Made with ♥ by https://www.lesli.tech
23
+ Made with ♥ by LesliTech
24
24
  Building a better future, one line of code at a time.
25
25
 
26
26
  @contact hello@lesli.tech
@@ -32,14 +32,15 @@ Building a better future, one line of code at a time.
32
32
  =end
33
33
  %>
34
34
 
35
+ <% devise_controller = controller_path.split('/')[1] %>
36
+
35
37
  <!DOCTYPE html>
36
38
  <html>
37
39
  <head>
38
40
  <script>const Lesli = <%= @lesli.to_json.html_safe %></script>
39
41
  <%= render partial: "lesli/partials/application-head" %>
40
42
  <%# render partial: "lesli/partials/application-data" %>
41
- <%= render partial: "lesli/partials/application-public-scss" %>
42
- <%= yield :application_custom_assets %>
43
+ <%= stylesheet_link_tag("lesli_shield/#{devise_controller}", media: "all") %>
43
44
  <%# Disable back button in browser after Logout using JavaScript %>
44
45
  <% if flash[:logout] == true %>
45
46
  <script>
@@ -51,9 +52,8 @@ Building a better future, one line of code at a time.
51
52
  <% end %>
52
53
  </head>
53
54
  <body class="<%= application_body_class() %>">
54
- <%#= yield :application_public_custom_header %>
55
55
  <%= yield %>
56
- <%= render partial: "lesli/partials/application-public-javascript" %>
56
+ <%= javascript_include_tag("lesli_shield/#{devise_controller}") %>
57
57
  <%= render partial: "lesli/partials/application-analytics" %>
58
58
  </body>
59
59
  </html>
@@ -47,7 +47,7 @@ Building a better future, one line of code at a time.
47
47
  <%= render partial: "lesli/partials/application-lesli-sidebar" %>
48
48
  <%= render partial: "lesli/partials/application-lesli-content" %>
49
49
  <%= render partial: "lesli/partials/application-lesli-engines" %>
50
- <%#= render partial: "lesli/partials/application-lesli-panels" %>
50
+ <%= render partial: "lesli/partials/application-lesli-panels" %>
51
51
  <%#= render partial: "lesli/partials/application-lesli-footer" %>
52
52
  </main>
53
53
  <%= render partial: "lesli/partials/application-lesli-javascript" %>
@@ -38,7 +38,7 @@ Building a better future, one line of code at a time.
38
38
 
39
39
  # add company information (account)
40
40
  @lesli[:company] = {
41
- name: current_user.account.company_name,
41
+ name: current_user.account.name,
42
42
  }
43
43
 
44
44
  # set user information
@@ -53,6 +53,7 @@ Building a better future, one line of code at a time.
53
53
  @lesli[:engine] = lesli_engine.dig(:code) # use into url plugin to for dynamic search
54
54
  @lesli[:url] = request.base_url.to_s # use as base for url plugin
55
55
  @lesli[:engine_paths] = {}
56
+
56
57
  %>
57
58
 
58
59
 
@@ -20,11 +20,11 @@ along with this program. If not, see http://www.gnu.org/licenses/.
20
20
 
21
21
  Lesli · Ruby on Rails SaaS Development Framework.
22
22
 
23
- Made with ♥ by https://www.lesli.tech
23
+ Made with ♥ by LesliTech
24
24
  Building a better future, one line of code at a time.
25
25
 
26
26
  @contact hello@lesli.tech
27
- @website https://www.lesli.dev
27
+ @website https://www.lesli.tech
28
28
  @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
29
29
 
30
30
  // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
@@ -35,49 +35,24 @@ Building a better future, one line of code at a time.
35
35
  <%# Standard module selector %>
36
36
  <lesli-application-engines>
37
37
 
38
- <%# Core %>
38
+ <%# 01. Administration %>
39
39
  <%= navigation_engine_admin %>
40
40
 
41
- <%# Administration %>
42
- <%= navigation_engine_team %>
43
-
44
- <%# Sales & marketing %>
45
- <%= navigation_engine_house %>
46
- <%= navigation_engine_word %>
47
- <%= navigation_engine_mailer %>
48
- <%= navigation_engine_proposal %>
49
-
50
- <%# Productivity & teamwork %>
51
- <%= navigation_engine_driver %>
52
- <%= navigation_engine_letter %>
53
- <%= navigation_engine_work %>
54
- <%= navigation_engine_focus %>
55
- <%= navigation_engine_social %>
41
+ <%# 03. Productivity & Teamwork%>
42
+ <%= navigation_engine_calendar %>
56
43
  <%= navigation_engine_bell %>
57
- <%= navigation_engine_time %>
58
- <%= navigation_engine_talk %>
59
- <%= navigation_engine_storage %>
60
-
61
- <%# Finance %>
62
- <%= navigation_engine_things %>
63
- <%= navigation_engine_realty %>
64
-
65
- <%# IT & Help desk %>
66
- <%= navigation_engine_kb %>
67
- <%= navigation_engine_portal %>
68
- <%= navigation_engine_shared %>
69
- <%= navigation_engine_support %>
70
44
 
71
- <%# Security & privacy %>
45
+ <%# 05. Analytics %>
72
46
  <%= navigation_engine_audit %>
73
- <%= navigation_engine_guard %>
74
47
 
75
- <%# Integrations %>
76
- <%= navigation_engine_babel %>
77
- <%= navigation_engine_federation %>
78
- <%= navigation_engine_development %>
48
+ <%# 07. IT & Help Desk %>
49
+ <%= navigation_engine_support %>
79
50
 
80
- <%# Intelligence %>
81
- <%= navigation_engine_scraper %>
51
+ <%# 08. Security & Privacy %>
52
+ <%= navigation_engine_shield %>
53
+ <%= navigation_engine_security %>
54
+
55
+ <%# 09. Integrations %>
56
+ <%= navigation_engine_babel %>
82
57
 
83
58
  </lesli-application-engines>
@@ -18,7 +18,7 @@ GNU General Public License for more details.
18
18
  You should have received a copy of the GNU General Public License
19
19
  along with this program. If not, see http://www.gnu.org/licenses/.
20
20
 
21
- Lesli · Ruby on Rails SaaS development platform.
21
+ Lesli · Ruby on Rails SaaS Development Framework.
22
22
 
23
23
  Made with ♥ by https://www.lesli.tech
24
24
  Building a better future, one line of code at a time.
@@ -36,12 +36,12 @@ Building a better future, one line of code at a time.
36
36
  :show-engines="true"
37
37
  <%= "show-bell" if defined?(LesliBell) %>
38
38
  <%= "show-focus" if defined?(LesliFocus) %>
39
- <%= "show-tickets" if defined?(LesliHelp) %>
39
+ <%= "show-support-tickets" if defined?(LesliSupport) %>
40
40
  engine-path="<%= defined?(LesliDashboard) ? lesli_dashboard.root_path : lesli_engine(:path)%>">
41
41
 
42
42
  <template v-slot:brand>
43
- <%= customization_instance_logo_tag(logo: "app-icon", options: { alt: "App logo", class: "is-hidden-desktop" }) %>
44
- <%= customization_instance_logo_tag(logo: "app-logo", options: { alt: "App logo", class: "is-hidden-touch" }) %>
43
+ <%= customization_instance_logo_tag(logo: "app-icon", options: { alt: "Lesli app logo", class: "is-hidden-desktop" }) %>
44
+ <%= customization_instance_logo_tag(logo: "app-logo", options: { alt: "Lesli app logo", class: "is-hidden-touch" }) %>
45
45
  </template>
46
46
 
47
47
  <template>