lesli 5.0.11 → 5.0.12

Sign up to get free protection for your applications and to get access to all the features.
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>