lesli 5.0.11 → 5.0.13
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/app/assets/config/lesli_manifest.js +0 -13
- data/app/assets/icons/lesli/engine-security.svg +1 -0
- data/app/assets/icons/lesli/engine-shield.svg +1 -0
- data/app/assets/images/lesli/brand/app-logo.png +0 -0
- data/app/assets/images/lesli/lesli-logo.svg +4 -0
- data/app/assets/javascripts/lesli/templates/application.js +14 -0
- data/app/assets/javascripts/lesli/templates/public.js +14 -0
- data/app/assets/stylesheets/lesli/templates/application.css +1365 -293
- data/app/assets/stylesheets/lesli/templates/public.css +1 -1
- data/app/controllers/lesli/abouts_controller.rb +12 -18
- data/app/controllers/lesli/application_controller.rb +26 -25
- data/app/controllers/lesli/application_lesli_controller.rb +5 -6
- data/app/controllers/lesli/interfaces/application/authorization.rb +2 -2
- data/app/controllers/lesli/interfaces/application/customization.rb +1 -1
- data/app/controllers/lesli/interfaces/application/requester.rb +2 -2
- data/app/controllers/lesli/interfaces/application/responder.rb +8 -8
- data/app/controllers/lesli/interfaces/controllers/actions.rb +250 -0
- data/app/controllers/lesli/interfaces/controllers/activities.rb +215 -0
- data/app/controllers/lesli/interfaces/controllers/discussions.rb +270 -0
- data/app/controllers/lesli/interfaces/controllers/files.rb +467 -0
- data/app/controllers/lesli/interfaces/controllers/subscribers.rb +234 -0
- data/app/helpers/lesli/assets_helper.rb +26 -8
- data/app/helpers/lesli/navigation_helper.rb +53 -92
- data/app/lib/date2.rb +8 -0
- data/app/lib/lesli/system.rb +17 -4
- data/app/models/concerns/account_initializer.rb +46 -42
- data/app/models/concerns/user_extensions.rb +6 -0
- data/{lib/scss/devise/registrations.scss → app/models/lesli/account/detail.rb} +7 -3
- data/app/models/lesli/account.rb +12 -5
- data/app/models/lesli/cloud_object/action.rb +70 -0
- data/app/models/lesli/cloud_object/activity.rb +311 -0
- data/app/models/lesli/cloud_object/custom_field.rb +158 -0
- data/app/models/lesli/cloud_object/discussion.rb +219 -0
- data/app/models/lesli/cloud_object/subscriber.rb +186 -0
- data/app/models/lesli/shared/dashboard.rb +16 -5
- data/app/models/lesli/user/session.rb +0 -2
- data/app/models/lesli/user.rb +13 -13
- data/app/operators/lesli/controller_operator.rb +4 -1
- data/app/operators/lesli/user_registration_operator.rb +3 -3
- data/app/services/lesli/user_service.rb +1 -1
- data/app/views/lesli/layouts/application-devise.html.erb +6 -6
- data/app/views/lesli/layouts/application-lesli.html.erb +3 -1
- data/app/views/lesli/partials/_application-data.html.erb +5 -4
- data/app/views/lesli/partials/_application-lesli-engines.html.erb +14 -39
- data/app/views/lesli/partials/_application-lesli-header.html.erb +50 -25
- data/app/views/lesli/partials/_application-lesli-icons.html.erb +1 -1
- data/app/views/lesli/partials/_application-lesli-javascript.html.erb +2 -2
- data/app/views/lesli/partials/_application-lesli-navigation.html.erb +8 -1
- data/app/views/lesli/partials/_application-lesli-panels.html.erb +7 -7
- data/app/views/lesli/partials/_application-lesli-scss.html.erb +2 -2
- data/app/views/lesli/wrappers/_application-devise-simple.erb +1 -1
- data/app/views/lesli/wrappers/_application-devise.html.erb +5 -7
- data/config/initializers/devise.rb +335 -335
- data/config/initializers/lesli.rb +9 -2
- data/config/locales/translations.en.yml +9 -3
- data/config/locales/translations.es.yml +9 -3
- data/config/locales/translations.fr.yml +30 -0
- data/config/locales/translations.it.yml +30 -0
- data/config/locales/translations.pt.yml +30 -0
- data/config/routes.rb +1 -10
- data/db/migrate/{v1.0/0010003010_create_lesli_user_details.rb → v1/0010000110_create_lesli_accounts.rb} +19 -13
- data/db/migrate/{v1.0/0010000110_create_lesli_accounts.rb → v1/0010001010_create_lesli_account_details.rb} +5 -7
- data/db/migrate/{v1.0/0010001010_create_lesli_account_settings.rb → v1/0010001110_create_lesli_account_settings.rb} +2 -2
- data/db/seed/development/accounts.rb +10 -7
- data/db/seed/development/users.rb +20 -20
- data/db/seed/production/accounts.rb +10 -7
- data/lib/generators/application_lesli_generator.rb +164 -0
- data/lib/generators/lesli/spec/USAGE +8 -0
- data/lib/generators/lesli/spec/spec_generator.rb +25 -0
- data/lib/generators/lesli/spec/templates/spec-factory.template +17 -0
- data/lib/generators/lesli/spec/templates/spec-model.template +70 -0
- data/lib/lesli/configuration.rb +1 -1
- data/lib/lesli/engine.rb +3 -14
- data/lib/{scss/devise/passwords.scss → lesli/r_spec.rb} +12 -5
- data/lib/lesli/routing.rb +51 -20
- data/lib/lesli/version.rb +2 -2
- data/lib/lesli.rb +1 -0
- data/lib/scss/cloud-objects/discussion.scss +8 -5
- data/lib/scss/layouts/application-component.scss +1 -1
- data/lib/scss/{devise/sessions.scss → layouts/application-content.scss} +4 -4
- data/lib/scss/layouts/application-header.scss +38 -108
- data/lib/scss/layouts/{application-navbar.scss → application-navigation.scss} +23 -5
- data/lib/scss/layouts/application-search.scss +1 -1
- data/lib/scss/{elements/msg.scss → overrides/notification.scss} +16 -18
- data/lib/scss/pages/devise-simple.scss +4 -2
- data/lib/scss/pages/devise.scss +111 -107
- data/lib/scss/panels/panel-notification.scss +1 -1
- data/lib/scss/panels/{panel-ticket.scss → panel-support-ticket.scss} +3 -4
- data/lib/scss/settings/variables.scss +1 -1
- data/lib/scss/templates/application.scss +14 -41
- data/lib/scss/templates/public.scss +6 -4
- data/lib/tasks/lesli/controllers.rake +1 -1
- data/lib/tasks/lesli/db.rake +24 -12
- data/lib/tasks/lesli_tasks.rake +7 -7
- data/lib/vue/application.js +18 -15
- data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/content.vue +10 -8
- data/lib/vue/cloudobjects/discussion/element.vue +170 -0
- data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/filters.vue +1 -1
- data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion/new.vue +20 -16
- data/lib/vue/{refactor/shared/cloudobjects → cloudobjects}/discussion.vue +25 -24
- data/lib/vue/{refactor/stores/cloudobjects → cloudobjects/stores}/discussion.js +7 -16
- data/lib/vue/layouts/application-component.vue +2 -2
- data/lib/vue/layouts/application-header.vue +109 -88
- data/lib/vue/panels/{panel-notifications.vue → panel-bell-notifications.vue} +15 -19
- data/lib/vue/panels/panel-support-tickets.vue +163 -0
- data/lib/vue/panels/stores/bell-notifications.js +46 -0
- data/lib/vue/panels/stores/support-tickets.js +103 -0
- data/lib/vue/shared/dashboards/apps/edit.vue +10 -10
- data/lib/vue/shared/dashboards/components/form.vue +31 -40
- data/lib/vue/shared/stores/dashboard.js +2 -0
- data/lib/vue/shared/stores/layout.js +2 -1
- data/lib/{scss/devise/confirmations.scss → vue/shared/stores/users.js} +22 -21
- data/lib/vue/stores/translations.json +119 -2
- data/lib/webpack/base.js +18 -12
- data/lib/webpack/core.js +16 -12
- data/lib/webpack/engines.js +3 -1
- data/lib/webpack/root.js +105 -0
- data/lib/webpack/version.js +37 -0
- data/readme.md +16 -15
- metadata +58 -92
- data/app/assets/icons/lesli/engine-guard.svg +0 -1
- data/app/assets/javascripts/lesli/users/sessions.js +0 -1
- data/app/assets/stylesheets/lesli/users/sessions.css +0 -1
- data/app/controllers/users/confirmations_controller.rb +0 -66
- data/app/controllers/users/omniauth_callbacks_controller.rb +0 -30
- data/app/controllers/users/passwords_controller.rb +0 -71
- data/app/controllers/users/registrations_controller.rb +0 -141
- data/app/controllers/users/sessions_controller.rb +0 -141
- data/app/controllers/users/unlocks_controller.rb +0 -30
- data/app/views/devise/confirmations/new.html.erb +0 -2
- data/app/views/devise/confirmations/show.html.erb +0 -63
- data/app/views/devise/mailer/confirmation_instructions.html.erb +0 -5
- data/app/views/devise/mailer/email_changed.html.erb +0 -7
- data/app/views/devise/mailer/password_change.html.erb +0 -3
- data/app/views/devise/mailer/reset_password_instructions.html.erb +0 -8
- data/app/views/devise/mailer/unlock_instructions.html.erb +0 -7
- data/app/views/devise/passwords/edit.html.erb +0 -79
- data/app/views/devise/passwords/new.html.erb +0 -75
- data/app/views/devise/registrations/edit.html.erb +0 -43
- data/app/views/devise/registrations/new.html.erb +0 -147
- data/app/views/devise/sessions/new.html.erb +0 -114
- data/app/views/devise/shared/_demo.html.erb +0 -7
- data/app/views/devise/shared/_error_messages.html.erb +0 -15
- data/app/views/devise/shared/_links.html.erb +0 -96
- data/app/views/devise/unlocks/new.html.erb +0 -16
- data/db/migrate/v1.0/0010000210_create_lesli_roles.rb +0 -59
- data/db/migrate/v1.0/0010000310_create_lesli_users.rb +0 -97
- data/db/migrate/v1.0/0010003110_create_lesli_user_settings.rb +0 -44
- data/db/migrate/v1.0/0010003210_create_lesli_user_sessions.rb +0 -55
- data/db/migrate/v1.0/0010003410_create_lesli_user_powers.rb +0 -43
- data/db/migrate/v1.0/0010004010_create_lesli_user_logs.rb +0 -45
- data/db/migrate/v1.0/0010005010_create_lesli_descriptors.rb +0 -44
- data/db/migrate/v1.0/0010005110_create_lesli_descriptor_privileges.rb +0 -45
- data/db/migrate/v1.0/0010005210_create_lesli_descriptor_activities.rb +0 -49
- data/db/migrate/v1.0/0010005510_create_lesli_role_powers.rb +0 -51
- data/db/migrate/v1.0/0010005710_create_lesli_role_privileges.rb +0 -45
- data/lib/scss/bulma/loader.scss +0 -92
- data/lib/scss/components/editor-richtext.scss +0 -88
- data/lib/scss/devise/oauth.scss +0 -34
- data/lib/scss/elements/avatar.scss +0 -48
- data/lib/scss/elements/calendar.scss +0 -47
- data/lib/scss/elements/toggle.scss +0 -102
- data/lib/vue/devise/confirmations.js +0 -33
- data/lib/vue/devise/passwords.js +0 -137
- data/lib/vue/devise/registrations.js +0 -157
- data/lib/vue/devise/sessions.js +0 -148
- data/lib/vue/panels/panel-tickets.vue +0 -181
- data/lib/vue/refactor/shared/cloudobjects/discussion/element.vue +0 -132
- data/lib/vue/shared/stores/account.js +0 -113
- /data/app/assets/icons/lesli/{engine-driver.svg → engine-calendar.svg} +0 -0
- /data/db/migrate/{v1.0 → v1}/0010000610_create_lesli_system_controllers.rb +0 -0
- /data/db/migrate/{v1.0 → v1}/0010000710_create_lesli_system_controller_actions.rb +0 -0
- /data/db/migrate/{v1.0 → v1}/0010001210_create_lesli_account_activities.rb +0 -0
- /data/db/migrate/{v1.0 → v1}/0010001410_create_lesli_account_logs.rb +0 -0
|
@@ -37,24 +37,41 @@ module AccountInitializer
|
|
|
37
37
|
# initialize minimum resources needed for the account
|
|
38
38
|
def initialize_account
|
|
39
39
|
|
|
40
|
+
return unless defined?(LesliSecurity)
|
|
41
|
+
|
|
40
42
|
# create initial descriptors
|
|
41
43
|
descriptor_owner = self.descriptors.find_or_create_by(name: "owner")
|
|
42
44
|
descriptor_admin = self.descriptors.find_or_create_by(name: "admin")
|
|
43
45
|
descriptor_profile = self.descriptors.find_or_create_by(name: "profile")
|
|
44
46
|
|
|
45
47
|
# create default roles for the new account
|
|
46
|
-
owner = self.roles.
|
|
48
|
+
owner = self.roles.create_with({
|
|
49
|
+
active: true,
|
|
50
|
+
object_level_permission: 2147483647
|
|
51
|
+
}).find_or_create_by(:name => "owner")
|
|
47
52
|
|
|
48
53
|
# platform administrator role
|
|
49
|
-
admin = self.roles.
|
|
54
|
+
admin = self.roles.create_with({
|
|
55
|
+
active: true, object_level_permission: 100000
|
|
56
|
+
}).find_or_create_by({ name: "admin" })
|
|
50
57
|
|
|
51
58
|
# access only to user profile
|
|
52
|
-
limited = self.roles.
|
|
59
|
+
limited = self.roles.create_with({
|
|
60
|
+
active: true, object_level_permission: 10, path_default: "/administration/profile"
|
|
61
|
+
}).find_or_create_by({ name: "limited" })
|
|
53
62
|
|
|
54
63
|
# assign descriptors with appropriate privileges
|
|
55
|
-
owner.powers.
|
|
56
|
-
|
|
57
|
-
|
|
64
|
+
owner.powers.create_with({
|
|
65
|
+
plist: true, pindex: true, pshow: true, pcreate: true, pupdate: true, pdestroy: true
|
|
66
|
+
}).find_or_create_by(:descriptor => descriptor_owner)
|
|
67
|
+
|
|
68
|
+
admin.powers.create_with({
|
|
69
|
+
plist: true, pindex: true, pshow: true, pcreate: true, pupdate: true, pdestroy: true
|
|
70
|
+
}).find_or_create_by(:descriptor => descriptor_admin)
|
|
71
|
+
|
|
72
|
+
limited.powers.create_with({
|
|
73
|
+
plist: true, pindex: true, pshow: true, pcreate: true, pupdate: true, pdestroy: true
|
|
74
|
+
}).find_or_create_by(:descriptor => descriptor_profile)
|
|
58
75
|
end
|
|
59
76
|
|
|
60
77
|
|
|
@@ -63,56 +80,43 @@ module AccountInitializer
|
|
|
63
80
|
|
|
64
81
|
# 01.01 LesliAdmin - Lesli administration area
|
|
65
82
|
if defined? LesliAdmin
|
|
66
|
-
if self.admin.blank?
|
|
67
|
-
self.admin = LesliAdmin::Account.new
|
|
68
|
-
self.admin.account = self
|
|
69
|
-
self.admin.save!
|
|
70
|
-
end
|
|
83
|
+
LesliAdmin::Account.create!(:account => self) if self.admin.blank?
|
|
71
84
|
end
|
|
72
85
|
|
|
73
|
-
# 03.01
|
|
74
|
-
if defined?
|
|
75
|
-
if self.
|
|
76
|
-
self.driver = LesliDriver::Account.new
|
|
77
|
-
self.driver.account = self
|
|
78
|
-
self.driver.save!
|
|
79
|
-
end
|
|
86
|
+
# 03.01 LesliCalendar - Unified calendar app
|
|
87
|
+
if defined? LesliCalendar
|
|
88
|
+
LesliCalendar::Account.create!(:account => self) if self.calendar.blank?
|
|
80
89
|
end
|
|
81
90
|
|
|
82
|
-
# 03.05
|
|
91
|
+
# 03.05 LesliLetter - Notes & Notebooks
|
|
83
92
|
if defined? LesliLetter
|
|
84
|
-
if self.letter.blank?
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
93
|
+
LesliLetter::Account.create!(:account => self) if self.letter.blank?
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
# 03.06 LesliDashboard -
|
|
97
|
+
if defined? LesliDashboard
|
|
98
|
+
LesliDashboard::Account.create!(:account => self) if self.dashboard.blank?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# 03.08 LesliBell - Notification system
|
|
102
|
+
if defined? LesliBell
|
|
103
|
+
LesliBell::Account.create!(:account => self) if self.bell.blank?
|
|
89
104
|
end
|
|
90
105
|
|
|
91
106
|
# 05.02 LesliAudit - System analytics
|
|
92
107
|
if defined? LesliAudit
|
|
93
|
-
if self.audit.blank?
|
|
94
|
-
self.audit = LesliAudit::Account.new
|
|
95
|
-
self.audit.account = self
|
|
96
|
-
self.audit.save!
|
|
97
|
-
end
|
|
108
|
+
LesliAudit::Account.create!(:account => self) if self.audit.blank?
|
|
98
109
|
end
|
|
99
110
|
|
|
100
|
-
# 07.02
|
|
101
|
-
if defined?
|
|
102
|
-
if self.
|
|
103
|
-
self.help = LesliHelp::Account.new
|
|
104
|
-
self.help.account = self
|
|
105
|
-
self.help.save!
|
|
106
|
-
end
|
|
111
|
+
# 07.02 LesliSupport - Support Ticket System
|
|
112
|
+
if defined? LesliSupport
|
|
113
|
+
LesliSupport::Account.create!(:account => self) if self.support.blank?
|
|
107
114
|
end
|
|
108
115
|
|
|
109
|
-
# 08.
|
|
116
|
+
# 08.02 LesliSecurity - Users, Privileges & Access Management
|
|
110
117
|
if defined? LesliGuard
|
|
111
|
-
if self.guard.blank?
|
|
112
|
-
self.guard = LesliGuard::Account.new
|
|
113
|
-
self.guard.account = self
|
|
114
|
-
self.guard.save!
|
|
115
|
-
end
|
|
118
|
+
LesliGuard::Account.create!(:account => self) if self.guard.blank?
|
|
116
119
|
end
|
|
120
|
+
|
|
117
121
|
end
|
|
118
122
|
end
|
|
@@ -57,6 +57,12 @@ module UserExtensions
|
|
|
57
57
|
end
|
|
58
58
|
|
|
59
59
|
|
|
60
|
+
# @return [String] The first name of this user.
|
|
61
|
+
def name2
|
|
62
|
+
self.first_name
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
|
|
60
66
|
# @return [String] The name of this user.
|
|
61
67
|
# @description Retrieves and returns the name of the user depending on the available information.
|
|
62
68
|
# The name can be a full name (first and last names), just the first name, or, in case the information
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
|
|
1
|
+
=begin
|
|
2
2
|
|
|
3
3
|
Lesli
|
|
4
4
|
|
|
@@ -28,6 +28,10 @@ Building a better future, one line of code at a time.
|
|
|
28
28
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
30
|
// ·
|
|
31
|
-
|
|
31
|
+
=end
|
|
32
32
|
|
|
33
|
-
|
|
33
|
+
module Lesli
|
|
34
|
+
class Account::Detail < ApplicationLesliRecord
|
|
35
|
+
belongs_to :account
|
|
36
|
+
end
|
|
37
|
+
end
|
data/app/models/lesli/account.rb
CHANGED
|
@@ -19,11 +19,11 @@ along with this program. If not, see http://www.gnu.org/licenses/.
|
|
|
19
19
|
|
|
20
20
|
Lesli · Ruby on Rails SaaS Development Framework.
|
|
21
21
|
|
|
22
|
-
Made with ♥ by
|
|
22
|
+
Made with ♥ by LesliTech
|
|
23
23
|
Building a better future, one line of code at a time.
|
|
24
24
|
|
|
25
25
|
@contact hello@lesli.tech
|
|
26
|
-
@website https://www.lesli.
|
|
26
|
+
@website https://www.lesli.tech
|
|
27
27
|
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
28
|
|
|
29
29
|
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
@@ -38,6 +38,10 @@ module Lesli
|
|
|
38
38
|
# accounts always belongs to a user
|
|
39
39
|
belongs_to :user, optional: true
|
|
40
40
|
|
|
41
|
+
#class_name: "Lesli::Account"
|
|
42
|
+
has_one :detail, inverse_of: :account, autosave: true, dependent: :destroy
|
|
43
|
+
accepts_nested_attributes_for :detail, update_only: true
|
|
44
|
+
|
|
41
45
|
|
|
42
46
|
# account resources
|
|
43
47
|
has_many :users
|
|
@@ -54,12 +58,15 @@ module Lesli
|
|
|
54
58
|
has_many :logs
|
|
55
59
|
|
|
56
60
|
|
|
61
|
+
has_one :bell, class_name: "LesliBell::Account"
|
|
57
62
|
has_one :help, class_name: "LesliHelp::Account"
|
|
58
63
|
has_one :audit, class_name: "LesliAudit::Account"
|
|
59
64
|
has_one :admin, class_name: "LesliAdmin::Account"
|
|
60
|
-
has_one :driver, class_name: "LesliDriver::Account"
|
|
61
|
-
has_one :letter, class_name: "LesliLetter::Account"
|
|
62
65
|
has_one :guard, class_name: "LesliGuard::Account"
|
|
66
|
+
has_one :letter, class_name: "LesliLetter::Account"
|
|
67
|
+
has_one :support, class_name: "LesliSupport::Account"
|
|
68
|
+
has_one :calendar, class_name: "LesliCalendar::Account"
|
|
69
|
+
has_one :dashboard, class_name: "LesliDashboard::Account"
|
|
63
70
|
|
|
64
71
|
|
|
65
72
|
# account statuses
|
|
@@ -80,7 +87,7 @@ module Lesli
|
|
|
80
87
|
|
|
81
88
|
|
|
82
89
|
# required a name for the lesli account
|
|
83
|
-
validates :
|
|
90
|
+
validates :name, :presence => true
|
|
84
91
|
|
|
85
92
|
|
|
86
93
|
# initializers for new accounts
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
=begin
|
|
2
|
+
|
|
3
|
+
Lesli
|
|
4
|
+
|
|
5
|
+
Copyright (c) 2023, Lesli Technologies, S. A.
|
|
6
|
+
|
|
7
|
+
This program is free software: you can redistribute it and/or modify
|
|
8
|
+
it under the terms of the GNU General Public License as published by
|
|
9
|
+
the Free Software Foundation, either version 3 of the License, or
|
|
10
|
+
(at your option) any later version.
|
|
11
|
+
|
|
12
|
+
This program is distributed in the hope that it will be useful,
|
|
13
|
+
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
14
|
+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
15
|
+
GNU General Public License for more details.
|
|
16
|
+
|
|
17
|
+
You should have received a copy of the GNU General Public License
|
|
18
|
+
along with this program. If not, see http://www.gnu.org/licenses/.
|
|
19
|
+
|
|
20
|
+
Lesli · Your Smart Business Assistant.
|
|
21
|
+
|
|
22
|
+
Made with ♥ by https://www.lesli.tech
|
|
23
|
+
Building a better future, one line of code at a time.
|
|
24
|
+
|
|
25
|
+
@contact hello@lesli.tech
|
|
26
|
+
@website https://lesli.tech
|
|
27
|
+
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
|
+
|
|
29
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
+
// ·
|
|
31
|
+
|
|
32
|
+
=end
|
|
33
|
+
module Lesli
|
|
34
|
+
class CloudObject::Action < ApplicationLesliRecord
|
|
35
|
+
self.abstract_class = true
|
|
36
|
+
|
|
37
|
+
belongs_to :user_creator, class_name: "::User", foreign_key: "users_id"
|
|
38
|
+
|
|
39
|
+
# @return [Class] The class of the association 'belongs_to'
|
|
40
|
+
# @description All actions belong to a *cloud_object*. This method returns the specific class of
|
|
41
|
+
# that cloud_object.
|
|
42
|
+
# @example
|
|
43
|
+
# puts DeutscheLeibrenten::Project::File.cloud_object_model.new # This will display an instance of DeutscheLeibrenten::Project
|
|
44
|
+
def self.cloud_object_model
|
|
45
|
+
self.reflect_on_association(:cloud_object).klass
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.index(curren_user, cloud_object)
|
|
49
|
+
action_groups = {}
|
|
50
|
+
cloud_object.actions.order(group: :asc).map do |action|
|
|
51
|
+
action_attributes = action.attributes.merge({
|
|
52
|
+
"user_creator_name" => action.user_creator.full_name,
|
|
53
|
+
"created_at_text" => LC::Date.to_string(action.created_at)
|
|
54
|
+
})
|
|
55
|
+
action_groups[action.group] = [] unless action_groups[action.group]
|
|
56
|
+
|
|
57
|
+
action_groups[action.group].push(action_attributes)
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
action_groups
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def show(current_user)
|
|
64
|
+
attributes.merge({
|
|
65
|
+
"user_creator_name" => user_creator.full_name,
|
|
66
|
+
"created_at_text" => LC::Date.to_string(created_at)
|
|
67
|
+
})
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,311 @@
|
|
|
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 Development Platform.
|
|
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://www.lesli.tech
|
|
27
|
+
@license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
|
|
28
|
+
|
|
29
|
+
// · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
|
|
30
|
+
// ·
|
|
31
|
+
|
|
32
|
+
=end
|
|
33
|
+
module Lesli
|
|
34
|
+
class CloudObject::Activity < ApplicationRecord
|
|
35
|
+
self.abstract_class = true
|
|
36
|
+
|
|
37
|
+
belongs_to :user_creator, class_name: "::User", foreign_key: "users_id", optional: true
|
|
38
|
+
|
|
39
|
+
# This enum can be overrided by the model that inherits from CloudObject::Activity
|
|
40
|
+
enum category: {
|
|
41
|
+
action_list: "action_list",
|
|
42
|
+
action_create: "action_create",
|
|
43
|
+
action_show: "action_show",
|
|
44
|
+
action_update: "action_update",
|
|
45
|
+
action_destroy: "action_destroy",
|
|
46
|
+
action_status: "action_status",
|
|
47
|
+
action_workflow_action_failed: "action_workflow_action_failed",
|
|
48
|
+
action_email_sent: "action_email_sent",
|
|
49
|
+
action_create_file: "action_create_file",
|
|
50
|
+
action_update_file: "action_update_file",
|
|
51
|
+
action_destroy_file: "action_destroy_file",
|
|
52
|
+
action_not_found_file: "action_not_found_file",
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
# @return [User] This method will always return nil
|
|
56
|
+
# @description At the current time, this is a dummy method that returns nil, so the function is_editable_by? in
|
|
57
|
+
# ApplicationLesliRecord will work without issues
|
|
58
|
+
def user_main
|
|
59
|
+
return nil
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# @return [Class] The class of the association 'belongs_to'
|
|
63
|
+
# @description All activities belong to a *cloud_object*. This method returns the specific class of
|
|
64
|
+
# that cloud_object.
|
|
65
|
+
# @example
|
|
66
|
+
# puts DeutscheLeibrenten::Project::Activity.cloud_object_model.new # This will display an instance of DeutscheLeibrenten::Project
|
|
67
|
+
def self.cloud_object_model
|
|
68
|
+
self.reflect_on_association(:cloud_object).klass
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
#######################################################################################
|
|
73
|
+
############################## Activities Log Methods ##############################
|
|
74
|
+
#######################################################################################
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
# @param current_user [User] The current logged user
|
|
78
|
+
# @param cloud_id [Integer] Id of the *cloud_object* to which this activities belongs to
|
|
79
|
+
# @param query [Query] that contains the search and pagination information
|
|
80
|
+
# @return [Array] Array of activities. Each activities contains a *responses* element,
|
|
81
|
+
# which is an array that has all its responses ordered by date
|
|
82
|
+
# @description Retrieves and returns all activities from a *cloud_object*
|
|
83
|
+
# @example
|
|
84
|
+
# @activities = activity_model.index(
|
|
85
|
+
# current_user,
|
|
86
|
+
# profile_id,
|
|
87
|
+
# @query
|
|
88
|
+
# )
|
|
89
|
+
def self.index(current_user, cloud_id, query)
|
|
90
|
+
cloud_object_model = self.cloud_object_model
|
|
91
|
+
account_model = cloud_object_model.reflect_on_association(:account).klass
|
|
92
|
+
translations_module = self.name.split("::")[0].gsub("Cloud", "").underscore
|
|
93
|
+
|
|
94
|
+
# get search string from query params
|
|
95
|
+
search_string = query[:search].downcase.gsub(" ","%") unless query[:search].blank?
|
|
96
|
+
|
|
97
|
+
activities = self
|
|
98
|
+
.where("#{cloud_object_model.table_name}_id".to_sym => cloud_id)
|
|
99
|
+
.order(id: :desc)
|
|
100
|
+
.joins("inner join users u on #{self.table_name}.users_id = u.id")
|
|
101
|
+
.joins("inner join user_details ud on ud.users_id = u.id")
|
|
102
|
+
|
|
103
|
+
|
|
104
|
+
# Filter results by search string
|
|
105
|
+
unless search_string.blank?
|
|
106
|
+
# (LOWER(ud.last_name) SIMILAR TO '%#{search_string}%') OR
|
|
107
|
+
activities = activities.where("
|
|
108
|
+
(LOWER(#{self.table_name}.field_name) SIMILAR TO '%#{search_string}%') OR
|
|
109
|
+
(LOWER(#{self.table_name}.value_from) SIMILAR TO '%#{search_string}%') OR
|
|
110
|
+
(LOWER(#{self.table_name}.value_to) SIMILAR TO '%#{search_string}%') OR
|
|
111
|
+
(LOWER(ud.first_name) SIMILAR TO '%#{search_string}%')
|
|
112
|
+
")
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
activities = activities.map do |activity|
|
|
116
|
+
# We translate the category, first, we search in the core
|
|
117
|
+
category = I18n.t("core.shared.activities_enum_category_#{activity[:category]}", default: nil)
|
|
118
|
+
|
|
119
|
+
# Then we search in the engine
|
|
120
|
+
category = I18n.t("#{translations_module}.shared.activities_enum_category_#{activity[:category]}", default: nil) unless category
|
|
121
|
+
|
|
122
|
+
#Then we default to the real field
|
|
123
|
+
category = activity[:category] unless category
|
|
124
|
+
|
|
125
|
+
activity_attributes = activity.attributes
|
|
126
|
+
activity_attributes["category"] = category
|
|
127
|
+
activity_attributes["created_at_raw"] = activity[:created_at]
|
|
128
|
+
activity_attributes["created_at"] = LC::Date.to_string_datetime(activity[:created_at])
|
|
129
|
+
activity_attributes["updated_at"] = LC::Date.to_string_datetime(activity[:updated_at])
|
|
130
|
+
|
|
131
|
+
user = activity.user_creator
|
|
132
|
+
activity_attributes[:user_name] = user.full_name
|
|
133
|
+
|
|
134
|
+
activity_attributes
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
Kaminari.paginate_array(activities).page(query[:pagination][:page]).per(query[:pagination][:perPage])
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# @return [void]
|
|
141
|
+
# @param current_user [::User] The user that created the cloud_object
|
|
142
|
+
# @param cloud_object [CloudModule::Model] The cloud_object that was created
|
|
143
|
+
# @description Creates an activity for this cloud_object indicating who created it.
|
|
144
|
+
# Example
|
|
145
|
+
# params = {...}
|
|
146
|
+
# ticket = CloudHelp::Ticket.create(params)
|
|
147
|
+
# CloudHelp::Ticket.log_create(User.first, ticket)
|
|
148
|
+
def self.log_create(current_user, cloud_object)
|
|
149
|
+
cloud_object.activities.create(
|
|
150
|
+
user_creator: current_user,
|
|
151
|
+
category: "action_create"
|
|
152
|
+
)
|
|
153
|
+
|
|
154
|
+
# If cloud_object has workflow
|
|
155
|
+
if defined?(cloud_object.status)
|
|
156
|
+
module_name = cloud_object.class.lesli_classname().split("::")[0].underscore
|
|
157
|
+
cloud_object.activities.create(
|
|
158
|
+
user_creator: current_user,
|
|
159
|
+
category: "action_status",
|
|
160
|
+
description: cloud_object.status&.name,
|
|
161
|
+
field_name: "#{module_name}_workflow_statuses_id",
|
|
162
|
+
value_to: cloud_object.status&.name
|
|
163
|
+
)
|
|
164
|
+
end
|
|
165
|
+
|
|
166
|
+
yield if block_given?
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
# @return [void]
|
|
170
|
+
# @param current_user [::User] The user that created the cloud_object
|
|
171
|
+
# @param cloud_object [CloudModule::Model] The cloud_object that was shown
|
|
172
|
+
# @description Creates an activity for this cloud_object indicating who view it.
|
|
173
|
+
# Example
|
|
174
|
+
# params = {...}
|
|
175
|
+
# ticket = CloudHelp::Ticket.create(params)
|
|
176
|
+
# CloudHelp::Ticket.log_show(User.first, ticket)
|
|
177
|
+
def self.log_show(current_user, cloud_object)
|
|
178
|
+
cloud_object.activities.create(
|
|
179
|
+
user_creator: current_user,
|
|
180
|
+
category: "action_show"
|
|
181
|
+
)
|
|
182
|
+
|
|
183
|
+
yield if block_given?
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
# @return [void]
|
|
187
|
+
# @param current_user [::User] The user that edited the cloud_object
|
|
188
|
+
# @param cloud_object [CloudModule::Model] The cloud_object that was edited
|
|
189
|
+
# @param old_attributes[Hash] The data of the record before update
|
|
190
|
+
# @param new_attributes[Hash] The data of the record after update
|
|
191
|
+
# @description Creates an activity for this cloud_object if someone changed any of this values
|
|
192
|
+
# Example
|
|
193
|
+
# ticket = CloudHelp::Ticket.find(1)
|
|
194
|
+
# old_attributes = ticket.attributes
|
|
195
|
+
# ticket.update(user_main: User.find(33))
|
|
196
|
+
# new_attributes = ticket.attributes
|
|
197
|
+
# CloudHelp::TicketLogger.log_update(User.find(1), ticket, old_attributes, new_attributes)
|
|
198
|
+
def self.log_update(current_user, cloud_object, old_attributes, new_attributes, category: "action_update")
|
|
199
|
+
|
|
200
|
+
# We remove values that are not tracked in the activities
|
|
201
|
+
old_attributes.except!("id", "created_at", "updated_at", "deleted_at")
|
|
202
|
+
old_attributes.each do |key, value|
|
|
203
|
+
next if value == new_attributes[key]
|
|
204
|
+
if key.include?("id")
|
|
205
|
+
if key == "user_main_id" || key == "users_id" || key == "user_branch_office_id"
|
|
206
|
+
update_user_field(cloud_object, current_user, key, old_attributes[key], new_attributes[key], category)
|
|
207
|
+
elsif key.include?("workflow_statuses_id")
|
|
208
|
+
update_workflow_status_field(cloud_object, current_user, key, old_attributes[key], new_attributes[key])
|
|
209
|
+
else
|
|
210
|
+
update_field(cloud_object, current_user, key, old_attributes[key], new_attributes[key], category)
|
|
211
|
+
end
|
|
212
|
+
else
|
|
213
|
+
update_field(cloud_object, current_user, key, old_attributes[key], new_attributes[key], category)
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
|
|
217
|
+
yield if block_given?
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
# @return [void]
|
|
221
|
+
# @param current_user [::User] The user that deleted the cloud_object
|
|
222
|
+
# @param cloud_object [CloudModule::Model] The cloud_object that was destroyed
|
|
223
|
+
# @description Creates an activity for this cloud_object indicating that someone deleted it
|
|
224
|
+
# Example
|
|
225
|
+
# ticket = CloudHelp::Ticket.find(1)
|
|
226
|
+
# CloudHelp::TicketLogger.log_destroy(User.first, ticket)
|
|
227
|
+
# ticket.destroy
|
|
228
|
+
def self.log_destroy(current_user, cloud_object)
|
|
229
|
+
cloud_object.activities.create(
|
|
230
|
+
user_creator: current_user,
|
|
231
|
+
category: "action_destroy"
|
|
232
|
+
)
|
|
233
|
+
|
|
234
|
+
yield if block_given?
|
|
235
|
+
end
|
|
236
|
+
|
|
237
|
+
protected
|
|
238
|
+
|
|
239
|
+
# @return [void]
|
|
240
|
+
# @param current_user [User] The user that deleted the cloud_object
|
|
241
|
+
# @param cloud_object [CloudModule::Model] The cloud_object that updated
|
|
242
|
+
# @param key [String] The user field to be logged
|
|
243
|
+
# @param old_user_id [Integer] The id of the user prior to the update
|
|
244
|
+
# @param new_user_id [Integer] The id of the user after the update
|
|
245
|
+
# @description Logs an "action_update" activity. But instead of using the raw id of the user, it logs their name
|
|
246
|
+
# @example
|
|
247
|
+
# project = CloudHouse::Project.first
|
|
248
|
+
# CloudHouse::ProjectLogger.log_update(User.first, project, "users_id", 1, 2)
|
|
249
|
+
# # This will log a change from user with id 1 to user with id 2 using their names
|
|
250
|
+
def self.update_user_field(cloud_object, current_user, key, old_user_id, new_user_id, category)
|
|
251
|
+
cloud_object.activities.create(
|
|
252
|
+
user_creator: current_user,
|
|
253
|
+
category: category,
|
|
254
|
+
field_name: key,
|
|
255
|
+
value_from: old_user_id ? User.with_deleted.find(old_user_id).full_name : nil,
|
|
256
|
+
value_to: new_user_id ? User.with_deleted.find(new_user_id).full_name : nil
|
|
257
|
+
)
|
|
258
|
+
end
|
|
259
|
+
|
|
260
|
+
# @return [void]
|
|
261
|
+
# @param current_user [User] The user that deleted the cloud_object
|
|
262
|
+
# @param cloud_object [CloudModule::Model] The cloud_object that updated
|
|
263
|
+
# @param key [String] The user field to be logged
|
|
264
|
+
# @param old_workflow_status_id [Integer] The id of the workflow status prior to the update
|
|
265
|
+
# @param new_workflow_status_id [Integer] The id of the workflow status after the update
|
|
266
|
+
# @description Logs an "action_update" activity. But instead of using the raw id of the workflow status, it logs its name
|
|
267
|
+
# @example
|
|
268
|
+
# project = CloudHouse::Project.first
|
|
269
|
+
# CloudHouse::ProjectLogger.log_update(User.first, project, "cloud_house_workflow_statuses_id, 1, 2)
|
|
270
|
+
# # This will log a change from workflow status with id 1 to workflow status with id 2 using their names
|
|
271
|
+
def self.update_workflow_status_field(cloud_object, current_user, key, old_workflow_status_id, new_workflow_status_id)
|
|
272
|
+
module_name = cloud_object.class.lesli_classname().split("::")[0]
|
|
273
|
+
old_status = eval("#{module_name}::Workflow::Status").with_deleted.find(old_workflow_status_id).name
|
|
274
|
+
new_status = eval("#{module_name}::Workflow::Status").with_deleted.find(new_workflow_status_id).name
|
|
275
|
+
|
|
276
|
+
cloud_object.activities.create(
|
|
277
|
+
user_creator: current_user,
|
|
278
|
+
description: new_status,
|
|
279
|
+
category: "action_status",
|
|
280
|
+
field_name: key,
|
|
281
|
+
value_from: old_status,
|
|
282
|
+
value_to: new_status
|
|
283
|
+
)
|
|
284
|
+
end
|
|
285
|
+
|
|
286
|
+
# @return [void]
|
|
287
|
+
# @param current_user [User] The user that deleted the cloud_object
|
|
288
|
+
# @param cloud_object [CloudModule::Model] The cloud_object that updated
|
|
289
|
+
# @param key [String] The user field to be logged
|
|
290
|
+
# @param old_field [Integer] The value of the field prior to the update
|
|
291
|
+
# @param new_field [Integer] The value of the field after the update
|
|
292
|
+
# @description Logs an "action_update" activity. If the value that changed is a date, it uses LC::Date to turn it into a string
|
|
293
|
+
# otherwise, it logs it as is
|
|
294
|
+
# @example
|
|
295
|
+
# ticket = CloudHelp::Ticket.first
|
|
296
|
+
# CloudHelp::TicketLogger.log_update(User.first, ticket, "deadline": Time.now - 1.days, Time.now)
|
|
297
|
+
# # This will log a change from workflow on the deadline, and it will use the format specified by the lesli instance
|
|
298
|
+
def self.update_field(cloud_object, current_user, key, old_field, new_field, category)
|
|
299
|
+
old_field = LC::Date.to_string_datetime(old_field) if old_field.is_a?(Time) || old_field.is_a?(Date)
|
|
300
|
+
new_field = LC::Date.to_string_datetime(new_field) if new_field.is_a?(Time) || new_field.is_a?(Date)
|
|
301
|
+
|
|
302
|
+
cloud_object.activities.create(
|
|
303
|
+
user_creator: current_user,
|
|
304
|
+
category: category,
|
|
305
|
+
field_name: key,
|
|
306
|
+
value_from: old_field,
|
|
307
|
+
value_to: new_field
|
|
308
|
+
)
|
|
309
|
+
end
|
|
310
|
+
end
|
|
311
|
+
end
|