lesli_admin 0.3.0 → 0.5.0

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 (51) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/lesli_admin/application.js +1698 -4027
  3. data/app/assets/stylesheets/lesli_admin/application.scss +1 -1
  4. data/app/controllers/lesli_admin/accounts_controller.rb +3 -5
  5. data/app/controllers/lesli_admin/dashboard/components_controller.rb +60 -0
  6. data/app/controllers/lesli_admin/dashboards_controller.rb +26 -50
  7. data/app/controllers/lesli_admin/profiles_controller.rb +8 -16
  8. data/app/models/lesli_admin/account.rb +6 -0
  9. data/{lib/vue/apps/users/components/integrations-information.vue → app/models/lesli_admin/dashboard/component.rb} +24 -35
  10. data/app/models/lesli_admin/dashboard.rb +58 -0
  11. data/app/services/lesli_admin/account_service.rb +39 -0
  12. data/app/views/lesli_admin/dashboards/edit.html.erb +29 -7
  13. data/app/views/lesli_admin/dashboards/index.html.erb +29 -11
  14. data/app/views/lesli_admin/dashboards/new.html.erb +29 -6
  15. data/app/views/lesli_admin/dashboards/show.html.erb +31 -0
  16. data/app/views/lesli_admin/partials/_engine-navigation.html.erb +0 -1
  17. data/config/locales/translations.en.yml +33 -0
  18. data/config/locales/translations.es.yml +33 -0
  19. data/config/routes.rb +47 -4
  20. data/db/migrate/0101050110_create_lesli_admin_dashboards.rb +51 -0
  21. data/db/migrate/0101050210_create_lesli_admin_dashboard_components.rb +53 -0
  22. data/lib/lesli_admin/engine.rb +1 -0
  23. data/lib/lesli_admin/version.rb +1 -1
  24. data/lib/vue/application.js +37 -16
  25. data/lib/vue/apps/account/components/{address-form.vue → form-address.vue} +27 -42
  26. data/lib/vue/apps/account/components/form-contact.vue +122 -0
  27. data/lib/vue/apps/account/components/form-information.vue +12 -30
  28. data/lib/vue/apps/account/show.vue +13 -12
  29. data/{app/assets/stylesheets/lesli_admin/users.scss → lib/vue/apps/dashboards/components/lesli-version.vue} +38 -34
  30. data/lib/vue/apps/{profile/components/change-email.vue → dashboards/show.vue} +9 -6
  31. data/lib/vue/stores/translations.json +68 -18
  32. metadata +17 -30
  33. data/app/controllers/lesli_admin/users_controller.rb +0 -238
  34. data/app/services/lesli_admin/user_service.rb +0 -265
  35. data/app/views/lesli_admin/dashboards/_dashboard.html.erb +0 -2
  36. data/app/views/lesli_admin/dashboards/_form.html.erb +0 -17
  37. data/lib/vue/apps/account/components/contact-form.vue +0 -162
  38. data/lib/vue/apps/dashboard/show.vue +0 -30
  39. data/lib/vue/apps/profile/components/subscriptions.vue +0 -94
  40. data/lib/vue/apps/profile/show.vue +0 -152
  41. data/lib/vue/apps/users/components/information-card.vue +0 -116
  42. data/lib/vue/apps/users/components/information-form.vue +0 -177
  43. data/lib/vue/apps/users/components/management-roles.vue +0 -109
  44. data/lib/vue/apps/users/components/management-security.vue +0 -113
  45. data/lib/vue/apps/users/components/management-sessions.vue +0 -106
  46. data/lib/vue/apps/users/components/management-settings.vue +0 -94
  47. data/lib/vue/apps/users/index.vue +0 -206
  48. data/lib/vue/apps/users/new.vue +0 -181
  49. data/lib/vue/apps/users/show.vue +0 -116
  50. data/lib/vue/stores/user.js +0 -331
  51. data/lib/vue/stores/users.js +0 -175
@@ -1,265 +0,0 @@
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 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
- =end
32
-
33
- module LesliAdmin
34
- class UserService < Lesli::ApplicationLesliService
35
-
36
- # @return [Array] Paginated index of users.
37
- # @description Return a paginated array of users, used mostly in frontend views
38
- # TODO: Implement pg_search
39
- def index params
40
-
41
- # sql string to join to user_roles and get all the roles assigned to a user
42
- sql_string_for_user_roles = "left join (
43
- select
44
- ur.user_id, string_agg(r.\"name\", ', ') rolenames
45
- from user_roles ur
46
- join roles r
47
- on r.id = ur.role_id
48
- where ur.deleted_at is null
49
- group by ur.user_id
50
- ) roles on roles.user_id = users.id"
51
-
52
- # sql string to joing to user_sessions and get all the active sessions of a user
53
- sql_string_for_user_sessions = "left join (
54
- select
55
- max(last_used_at) as last_action_performed_at,
56
- user_id
57
- from user_sessions us
58
- where us.deleted_at is null
59
- group by(us.user_id)
60
- ) sessions on sessions.user_id = users.id"
61
-
62
- #users = current_user.account.users
63
- users = Lesli::Account.first.users
64
- #.joins(sql_string_for_user_roles)
65
- #.joins(sql_string_for_user_sessions)
66
- users = users.page(query[:pagination][:page])
67
- .per(query[:pagination][:perPage])
68
- .order("#{query[:order][:by]} #{query[:order][:dir]} NULLS LAST")
69
-
70
- users.select(
71
- :id,
72
- "CONCAT(COALESCE(first_name, ''), ' ', COALESCE(last_name, '')) as name",
73
- :email,
74
- :active,
75
- #:rolenames,
76
- #Date2.new.date_time.db_column("current_sign_in_at"),
77
- #Date2.new.date_time.db_column("last_action_performed_at")
78
- )
79
-
80
- end
81
-
82
-
83
- # Creates a query that selects all user information from several tables if CloudLock is present
84
- def show
85
-
86
- user = resource
87
-
88
- return {
89
- id: user[:id],
90
- email: user[:email],
91
- alias: user[:alias],
92
- active: user[:active],
93
- full_name: user.full_name,
94
- salutation: user[:salutation],
95
- first_name: user[:first_name],
96
- last_name: user[:last_name],
97
- telephone: user[:telephone],
98
-
99
- #locale: user.settings.select(:value).find_by(:name => "locale"),
100
-
101
- #roles: user.roles.map { |r| { id: r[:id], name: r[:name], permission_level: r[:object_level_permission]} },
102
-
103
- #mfa_enabled: user.mfa_settings[:enabled],
104
- #mfa_method: user.mfa_settings[:method],
105
-
106
- created_at: user[:created_at],
107
- updated_at: user[:updated_at],
108
- detail_attributes: {
109
- title: user.detail&[:title] || "",
110
- # address: user.detail[:address],
111
- # work_city: user.detail[:work_city],
112
- # work_region: user.detail[:work_region],
113
- # work_address: user.detail[:work_address]
114
- }
115
- }
116
- end
117
-
118
- def create user_params
119
-
120
- # check if request has an email to create the user
121
- if user_params[:email].blank?
122
- self.error(I18n.t("core.users.messages_danger_not_valid_email_found"))
123
- end
124
-
125
-
126
- # register the new user
127
- user = User.new({
128
- :active => true,
129
- :email => user_params[:email],
130
- :alias => user_params[:alias] || "",
131
- :first_name => user_params[:first_name] || "",
132
- :last_name => user_params[:last_name] || "",
133
- :telephone => user_params[:telephone] || "",
134
- #:detail_attributes => user_params[:detail_attributes] || {}
135
- })
136
-
137
-
138
-
139
- # assign a random password
140
- user.password = Devise.friendly_token
141
-
142
- # enrol user to my own account
143
- user.account = current_user.account
144
-
145
- # users created through the administration area does not need to confirm their accounts
146
- # instead we send a password reset link, so they can have access to the platform
147
- #user.confirm
148
-
149
- if user.save
150
-
151
- # if a role is provided to assign to the new user
152
- # unless user_params[:roles_id].blank?
153
- # # check if current user can work with the sent role
154
- # if current_user.can_work_with_role?(user_params[:roles_id])
155
- # # Search the role assigned
156
- # role = current_user.account.roles.find_by(id: user_params[:roles_id])
157
- # # assign role to the new user
158
- # user.user_roles.create({ role: role })
159
- # end
160
- # end
161
-
162
- # role validation - if new user does not have any role assigned
163
- # if user.roles.blank?
164
-
165
- # default_role_id = current_user.account.settings.find_by(:name => "default_role_id")&.value
166
- # owner_role_id = current_user.account.roles.find_by(:name => "owner").id
167
- # if default_role_id.present? && default_role_id != owner_role_id
168
- # # assign default role
169
- # user.user_roles.create({ role: current_user.account.roles.find_by(:id => default_role_id)})
170
-
171
- # else
172
- # # assign limited role
173
- # user.user_roles.create({ role: current_user.account.roles.find_by(:name => "limited") })
174
- # end
175
- # end
176
-
177
- # saving logs with information about the creation of the user
178
- # user.logs.create({ title: "user_created_at", description: Date2.new.date_time.to_s })
179
- # user.logs.create({ title: "user_created_by", description: current_user.email })
180
- # user.logs.create({ title: "user_created_with_role", description: user.user_roles.first.role.name + " " + user.user_roles.first.role.id.to_s})
181
- # User.log_activity_create(current_user, user)
182
-
183
- self.resource = user
184
-
185
- begin
186
- # users created through the administration area does not need to confirm their accounts
187
- # instead we send a password reset link, so they can have access to the platform
188
- #UserMailer.with(user: user).invitation_instructions.deliver_now
189
- rescue => exception
190
- #Honeybadger.notify(exception)
191
- #user.logs.create({ title: "user_creation_email_failed ", description: exception.message })
192
- end
193
-
194
- else
195
- self.error(user.errors.full_messages.to_sentence)
196
- end
197
-
198
- self
199
-
200
- end
201
-
202
- def update params
203
-
204
- # old_attributes = resource.detail.attributes.merge({
205
- # active: resource.active
206
- # })
207
-
208
- if resource.update(params)
209
- # new_attributes = resource.detail.attributes.merge({
210
- # active: resource.active
211
- # })
212
- #resource.log_activity_update(current_user, resource, old_attributes, new_attributes)
213
- else
214
- self.error(resource.errors.full_messages.to_sentence)
215
- end
216
-
217
- self
218
- end
219
-
220
-
221
- # force the user to change the password (at next login)
222
- def request_password
223
-
224
- # expire password
225
- resource.set_password_as_expired
226
-
227
- resource.logs.create({ title: "request_password", description: "by_user: " + current_user.email })
228
- end
229
-
230
-
231
- # generate a random password for the user
232
- def password_reset
233
-
234
- # generate random password
235
- pass = resource.password_reset
236
-
237
- resource.logs.create({ title: "password_reset", description: "by_user: " + current_user.email })
238
-
239
- pass
240
- end
241
-
242
- def logout
243
- # delete user active sessions
244
- resource.sessions.destroy_all
245
-
246
- resource.logs.create({ title: "close_sessions", description: "by_user: " + current_user.email })
247
- end
248
-
249
- def revoke_access
250
-
251
- # delete user active sessions
252
- self.logout
253
-
254
- # add delete date to the last active session
255
- resource.revoke_access
256
-
257
- resource.logs.create({ title: "revoke_access", description: "by_user: " + current_user.email })
258
- end
259
-
260
- def find id
261
- #super(current_user.account.users.joins(:detail).find_by(id: id))
262
- super(current_user.account.users.find_by(id: id))
263
- end
264
- end
265
- end
@@ -1,2 +0,0 @@
1
- <div id="<%= dom_id dashboard %>">
2
- </div>
@@ -1,17 +0,0 @@
1
- <%= form_with(model: dashboard) do |form| %>
2
- <% if dashboard.errors.any? %>
3
- <div style="color: red">
4
- <h2><%= pluralize(dashboard.errors.count, "error") %> prohibited this dashboard from being saved:</h2>
5
-
6
- <ul>
7
- <% dashboard.errors.each do |error| %>
8
- <li><%= error.full_message %></li>
9
- <% end %>
10
- </ul>
11
- </div>
12
- <% end %>
13
-
14
- <div>
15
- <%= form.submit %>
16
- </div>
17
- <% end %>
@@ -1,162 +0,0 @@
1
- <script setup>
2
- /*
3
-
4
- Lesli
5
-
6
- Copyright (c) 2023, Lesli Technologies, S. A.
7
-
8
- This program is free software: you can redistribute it and/or modify
9
- it under the terms of the GNU General Public License as published by
10
- the Free Software Foundation, either version 3 of the License, or
11
- (at your option) any later version.
12
-
13
- This program is distributed in the hope that it will be useful,
14
- but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- GNU General Public License for more details.
17
-
18
- You should have received a copy of the GNU General Public License
19
- along with this program. If not, see http://www.gnu.org/licenses/.
20
-
21
- Lesli · Your Smart Business Assistant.
22
-
23
- Made with ♥ by https://www.lesli.tech
24
- Building a better future, one line of code at a time.
25
-
26
- @contact hello@lesli.tech
27
- @website https://lesli.tech
28
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
29
-
30
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
31
- // ·
32
-
33
- */
34
-
35
-
36
- // · import vue tools
37
- import { computed } from "vue"
38
-
39
- // · import lesli stores
40
- import { useAccount } from "CloudAdmin/stores/account"
41
-
42
- // · implement stores
43
- const storeAccount = useAccount()
44
-
45
- // · translations
46
- const translations = {
47
- shared: I18n.t("core.shared"),
48
- core: {
49
- onboardings: I18n.t("core.onboardings"),
50
- accounts: I18n.t("core.accounts"),
51
- }
52
- }
53
-
54
- // . get reactive info from onboarding store
55
- const companyInfo = computed(()=> storeOnboarding.companyInfo)
56
-
57
- </script>
58
- <template>
59
- <form @submit.prevent="storeAccount.updateInfo">
60
- <div class="field">
61
- <label class="label">{{ translations.core.onboardings.view_text_email }}</label>
62
- <div class="control">
63
- <input
64
- class="input"
65
- type="text"
66
- :placeholder="translations.core.onboardings.view_placeholder_email"
67
- v-model="storeAccount.accountInfo.public_email"
68
- />
69
- </div>
70
- </div>
71
-
72
- <div class="field">
73
- <label class="label">{{translations.shared.view_text_telephone}}</label>
74
- <div class="control">
75
- <input
76
- class="input"
77
- type="text"
78
- :placeholder= "translations.core.onboardings.view_placeholder_phone"
79
- v-model="storeAccount.accountInfo.phone_number_1"
80
- />
81
- </div>
82
- </div>
83
-
84
- <p>{{translations.core.onboardings.view_title_social_profiles}}</p>
85
-
86
- <div class="field">
87
- <label class="label">{{ translations.core.accounts.column_github }}</label>
88
- <div class="control">
89
- <input
90
- class="input"
91
- type="text"
92
- :placeholder="translations.core.onboardings.view_placeholder_github"
93
- v-model="storeAccount.accountInfo.github"
94
- />
95
- </div>
96
- </div>
97
-
98
-
99
- <div class="field">
100
- <label class="label">{{ translations.core.accounts.column_twitter }}</label>
101
- <div class="control">
102
- <input
103
- class="input"
104
- type="text"
105
- :placeholder="translations.core.onboardings.view_placeholder_twitter"
106
- v-model="storeAccount.accountInfo.twitter"
107
- />
108
- </div>
109
- </div>
110
-
111
-
112
- <div class="field">
113
- <label class="label">{{ translations.core.accounts.column_youtube }}</label>
114
- <div class="control">
115
- <input
116
- class="input"
117
- type="text"
118
- :placeholder="translations.core.onboardings.view_placeholder_youtube"
119
- v-model="storeAccount.accountInfo.youtube"
120
- />
121
- </div>
122
- </div>
123
-
124
-
125
- <div class="field">
126
- <label class="label">{{ translations.core.accounts.column_linkedin }}</label>
127
- <div class="control">
128
- <input
129
- class="input"
130
- type="text"
131
- :placeholder="translations.core.onboardings.view_placeholder_linkedin"
132
- v-model="storeAccount.accountInfo.linkedin"
133
- />
134
- </div>
135
- </div>
136
-
137
-
138
- <div class="field">
139
- <label class="label">{{ translations.core.accounts.column_facebook }}</label>
140
- <div class="control">
141
- <input
142
- class="input"
143
- type="text"
144
- :placeholder="translations.core.onboardings.view_placeholder_facebook"
145
- v-model="storeAccount.accountInfo.facebook"
146
- />
147
- </div>
148
- </div>
149
-
150
- <div class="field">
151
- <div class="field-body">
152
- <div class="field">
153
- <div class="control">
154
- <lesli-button icon="save">
155
- {{ translations.shared.view_btn_save }}
156
- </lesli-button>
157
- </div>
158
- </div>
159
- </div>
160
- </div>
161
- </form>
162
- </template>
@@ -1,30 +0,0 @@
1
- <script setup>
2
-
3
- import { lesliChartLine } from "lesli-vue/components"
4
-
5
- </script>
6
- <template>
7
- <lesli-application-container>
8
- <lesli-header title="Dashboard"></lesli-header>
9
- <div class="columns">
10
- <div class="column">
11
- <lesli-application-component>
12
- <lesli-chart-line
13
- title="My daily activity graph"
14
- :series="[{ data:[4, 1, 4, 2, 5] }]"
15
- :labels="['Monday','Tuesday','Wednesday', 'Thursday', 'Friday']">
16
- </lesli-chart-line>
17
- </lesli-application-component>
18
- </div>
19
- <div class="column">
20
- <lesli-application-component>
21
- <lesli-chart-line
22
- title="My daily activity graph"
23
- :series="[{ name: 'Last week', data:[4, 1, 4, 2, 5] }, { name: 'Current week', data:[3, 2, 5, 4, 2] }]"
24
- :labels="['Monday','Tuesday','Wednesday', 'Thursday', 'Friday']">
25
- </lesli-chart-line>
26
- </lesli-application-component>
27
- </div>
28
- </div>
29
- </lesli-application-container>
30
- </template>
@@ -1,94 +0,0 @@
1
- <script setup>
2
- /*
3
-
4
- Lesli
5
-
6
- Copyright (c) 2023, Lesli Technologies, S. A.
7
-
8
- This program is free software: you can redistribute it and/or modify
9
- it under the terms of the GNU General Public License as published by
10
- the Free Software Foundation, either version 3 of the License, or
11
- (at your option) any later version.
12
-
13
- This program is distributed in the hope that it will be useful,
14
- but WITHOUT ANY WARRANTY; without even the implied warranty of
15
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
- GNU General Public License for more details.
17
-
18
- You should have received a copy of the GNU General Public License
19
- along with this program. If not, see http://www.gnu.org/licenses/.
20
-
21
- Lesli · Your Smart Business Assistant.
22
-
23
- Made with ♥ by https://www.lesli.tech
24
- Building a better future, one line of code at a time.
25
-
26
- @contact hello@lesli.tech
27
- @website https://lesli.tech
28
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
29
-
30
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
31
- // ·
32
-
33
- */
34
-
35
-
36
-
37
- // · import vue tools
38
- import { ref, reactive, onMounted, watch, computed } from "vue"
39
-
40
-
41
- // · import lesli stores
42
- import { useUser } from "LesliApp/administration/stores/user"
43
-
44
- // · implement stores
45
- const storeUser = useUser()
46
-
47
- const engine = ref({ label:"", value:"" })
48
-
49
-
50
- onMounted(() => {
51
- storeUser.getSubscriptionsOptions ()
52
- })
53
-
54
- function selectEngine(){
55
- storeUser.getSubscriptions(engine.value.value)
56
-
57
- }
58
-
59
-
60
- const translations = {
61
- users: I18n.t("core.users"),
62
- shared: I18n.t("core.shared")
63
- }
64
-
65
- const columns = [{
66
- field: 'action',
67
- label: 'action'
68
- }, {
69
- field: 'notification_type',
70
- label: 'Notification type'
71
- }, {
72
- field: 'created_at',
73
- label: 'Created at'
74
- }]
75
-
76
- </script>
77
- <template>
78
-
79
- <div class="block">
80
- <lesli-select
81
- :options="storeUser.options.engines"
82
- @change="selectEngine"
83
- v-model="engine">
84
- </lesli-select>
85
- </div>
86
- <lesli-table
87
- :columns="columns"
88
- :records="storeUser.subscriptions">
89
- </lesli-table>
90
-
91
-
92
-
93
- </template>
94
-