lesli_admin 0.3.0 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/lesli_admin/application.js +284 -841
  3. data/app/controllers/lesli_admin/accounts_controller.rb +3 -5
  4. data/app/controllers/lesli_admin/dashboard/components_controller.rb +60 -0
  5. data/app/controllers/lesli_admin/dashboards_controller.rb +26 -50
  6. data/app/models/lesli_admin/account.rb +6 -0
  7. data/app/{controllers/lesli_admin/profiles_controller.rb → models/lesli_admin/dashboard/component.rb} +13 -19
  8. data/app/models/lesli_admin/dashboard.rb +58 -0
  9. data/app/services/lesli_admin/account_service.rb +39 -0
  10. data/app/views/lesli_admin/dashboards/edit.html.erb +29 -7
  11. data/app/views/lesli_admin/dashboards/index.html.erb +29 -11
  12. data/app/views/lesli_admin/dashboards/new.html.erb +29 -6
  13. data/app/views/lesli_admin/dashboards/show.html.erb +31 -0
  14. data/app/views/lesli_admin/partials/_engine-navigation.html.erb +0 -1
  15. data/config/locales/translations.en.yml +26 -0
  16. data/config/locales/translations.es.yml +26 -0
  17. data/config/routes.rb +46 -5
  18. data/db/migrate/0101050110_create_lesli_admin_dashboards.rb +51 -0
  19. data/db/migrate/0101050210_create_lesli_admin_dashboard_components.rb +53 -0
  20. data/lib/lesli_admin/engine.rb +1 -0
  21. data/lib/lesli_admin/version.rb +1 -1
  22. data/lib/vue/application.js +28 -15
  23. data/lib/vue/apps/account/components/{address-form.vue → form-address.vue} +27 -42
  24. data/lib/vue/apps/account/components/form-contact.vue +122 -0
  25. data/lib/vue/apps/account/components/form-information.vue +12 -30
  26. data/lib/vue/apps/account/show.vue +13 -12
  27. data/lib/vue/apps/{users/components/integrations-information.vue → dashboards/components/lesli-version.vue} +36 -26
  28. data/lib/vue/apps/{profile/components/change-email.vue → dashboards/show.vue} +9 -6
  29. data/lib/vue/stores/translations.json +52 -18
  30. metadata +17 -30
  31. data/app/controllers/lesli_admin/users_controller.rb +0 -238
  32. data/app/services/lesli_admin/user_service.rb +0 -265
  33. data/app/views/lesli_admin/dashboards/_dashboard.html.erb +0 -2
  34. data/app/views/lesli_admin/dashboards/_form.html.erb +0 -17
  35. data/lib/vue/apps/account/components/contact-form.vue +0 -162
  36. data/lib/vue/apps/dashboard/show.vue +0 -30
  37. data/lib/vue/apps/profile/components/subscriptions.vue +0 -94
  38. data/lib/vue/apps/profile/show.vue +0 -152
  39. data/lib/vue/apps/users/components/information-card.vue +0 -116
  40. data/lib/vue/apps/users/components/information-form.vue +0 -177
  41. data/lib/vue/apps/users/components/management-roles.vue +0 -109
  42. data/lib/vue/apps/users/components/management-security.vue +0 -113
  43. data/lib/vue/apps/users/components/management-sessions.vue +0 -106
  44. data/lib/vue/apps/users/components/management-settings.vue +0 -94
  45. data/lib/vue/apps/users/index.vue +0 -206
  46. data/lib/vue/apps/users/new.vue +0 -181
  47. data/lib/vue/apps/users/show.vue +0 -116
  48. data/lib/vue/stores/user.js +0 -331
  49. data/lib/vue/stores/users.js +0 -175
@@ -1,116 +0,0 @@
1
- <script setup>
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
- */
32
-
33
-
34
- // · import vue tools
35
- import { ref, onMounted } from "vue"
36
- import { useRouter, useRoute } from 'vue-router'
37
-
38
-
39
- // · import lesli stores
40
- import { useUser } from "LesliAdmin/stores/user"
41
-
42
-
43
- // · implement stores
44
- const storeUser = useUser()
45
- const router = useRouter()
46
- const route = useRoute()
47
-
48
-
49
- // · import profile components
50
- import informationCard from "LesliAdmin/apps/users/components/information-card.vue"
51
- import informationForm from "LesliAdmin/apps/users/components/information-form.vue"
52
- /*
53
- import informationForm from "CloudAdmin/apps/users/components/information-form.vue"
54
-
55
- import managementRoles from "CloudAdmin/apps/users/components/management-roles.vue"
56
- import managementSession from "CloudAdmin/apps/users/components/management-sessions.vue"
57
- import managementSecurity from "CloudAdmin/apps/users/components/management-security.vue"
58
- import managementSettings from "CloudAdmin/apps/users/components/management-settings.vue"
59
- */
60
-
61
-
62
-
63
-
64
- // · translations
65
- const translations = {
66
- core: {
67
- roles: I18n.t("core.roles"),
68
- users: I18n.t("core.users"),
69
- shared: I18n.t("core.shared")
70
- }
71
- }
72
-
73
-
74
- // ·
75
- const tab = ref(0)
76
-
77
-
78
- // · initializing
79
- onMounted(() => {
80
- // storeUser.$reset()
81
- // storeUser.getOptions()
82
- storeUser.getUser(route.params?.id)
83
- })
84
- </script>
85
- <template>
86
- <lesli-application-container>
87
- <information-card></information-card>
88
- <lesli-tabs v-model="tab">
89
- <lesli-tab-item icon="info_outline" title="Information">
90
- <information-form></information-form>
91
- </lesli-tab-item>
92
- </lesli-tabs>
93
- </lesli-application-container>
94
- <!--
95
- <application-component>
96
- <information-card></information-card>
97
- <lesli-tabs v-model="tab" v-if="storeUser.user.id">
98
- <lesli-tab-item icon="info_outline" :title="translations.core.users.view_tab_title_information">
99
- <information-form></information-form>
100
- </lesli-tab-item>
101
- <lesli-tab-item icon="security" :title="translations.core.users.view_tab_title_roles_and_privileges">
102
- <management-roles></management-roles>
103
- </lesli-tab-item>
104
- <lesli-tab-item icon="lock_outline" :title="translations.core.users.view_tab_title_security || 'Security'">
105
- <management-security></management-security>
106
- </lesli-tab-item>
107
- <lesli-tab-item icon="devices" :title="translations.core.users.view_tab_title_session || 'Sessions'" paddingless>
108
- <management-session></management-session>
109
- </lesli-tab-item>
110
- <lesli-tab-item icon="settings" :title="translations.core.users.view_tab_title_settings">
111
- <management-settings></management-settings>
112
- </lesli-tab-item>
113
- </lesli-tabs>
114
- </application-component>
115
- -->
116
- </template>
@@ -1,331 +0,0 @@
1
- /*
2
- Lesli
3
-
4
- Copyright (c) 2023, Lesli Technologies, S. A.
5
-
6
- This program is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- This program is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU General Public License for more details.
15
-
16
- You should have received a copy of the GNU General Public License
17
- along with this program. If not, see http://www.gnu.org/licenses/.
18
-
19
- Lesli · Ruby on Rails Development Platform.
20
-
21
- Made with ♥ by https://www.lesli.tech
22
- Building a better future, one line of code at a time.
23
-
24
- @contact hello@lesli.tech
25
- @website https://www.lesli.tech
26
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
27
-
28
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
29
- // ·
30
- */
31
-
32
-
33
- // ·
34
- import { defineStore } from "pinia"
35
-
36
-
37
- // ·
38
- export const useUser = defineStore("lesli.user", {
39
- state: () => {
40
- return {
41
- options: {
42
- regions: [],
43
- locales: [],
44
- salutations: [],
45
- mfa_methods: []
46
- },
47
- user: {
48
- roles_id: null,
49
- email: null,
50
- alias: null,
51
- first_name: null,
52
- last_name: null,
53
- telephone: null,
54
- detail_attributes: {
55
- salutation: null,
56
- title: null,
57
- }
58
- },
59
- roles: [],
60
- sessions: {
61
- pagination: {},
62
- records: []
63
- },
64
- options: {
65
- salutations: [],
66
- locales: []
67
- }
68
- }
69
- },
70
- getters: {
71
- initials() {
72
- let initials = ""
73
- if (this.user?.first_name) initials += this.user?.first_name[0];
74
- if (this.user?.last_name) initials += this.user?.last_name[0];
75
- return initials.toUpperCase()
76
- }
77
- },
78
- actions: {
79
-
80
- getOptions() {
81
- this.http.get(this.url.lesli("users/options")).then(result => {
82
- this.options = result
83
- })
84
- },
85
-
86
- getUser(id=null) {
87
-
88
- let url = this.url.admin("profile")
89
-
90
- if (id !== null) {
91
- console.log("aqui")
92
- url = this.url.admin("users/:id", id)
93
- }
94
-
95
- // get an specifick user if id is provided
96
- this.http.get(url).then(result => {
97
- this.user = result
98
- this.user.password = ""
99
- this.user.password_confirmation = ""
100
-
101
- this.language = result.locale ? result.locale.value : this.language
102
-
103
- // Backend should return the list of roles ordered by object level permission
104
- this.role_names = result.roles[0].name
105
-
106
- }).catch(error => {
107
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
108
- }).finally(() => {
109
- this.loading = false
110
- })
111
- },
112
-
113
- putUser() {
114
- this.http.put(this.url.lesli("users/:id", this.user.id), {
115
- user: {
116
- active: this.user.active,
117
- alias: this.user.alias,
118
- first_name: this.user.first_name,
119
- last_name: this.user.last_name,
120
- telephone: this.user.telephone,
121
- detail_attributes: {
122
- title: this.user.detail_attributes.title,
123
- salutation: this.user.detail_attributes.salutation
124
- }
125
- }
126
- }).then(result => {
127
- this.msg.success(I18n.t("core.users.messages_success_operation"))
128
- }).catch(error => {
129
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
130
- })
131
- },
132
-
133
- deleteUser() {
134
- this.dialog.confirmation({
135
- title: "Delete user",
136
- text: "Are you sure you want to delete user?",
137
- confirmText: "Yes",
138
- cancelText: "No"
139
- })
140
- .then(({ isConfirmed }) => {
141
- if (isConfirmed) {
142
- this.http.delete(this.url.lesli("/users/:id", this.user.id)).then(result => {
143
- this.msg.success(I18n.t("core.users.messages_success_operation"))
144
- //this.url.go("/administration/users")
145
- }).catch(error => {
146
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
147
- })
148
- }
149
- })
150
- },
151
-
152
- getRoles() {
153
- this.http.get(this.url.lesli("users/:id/roles", this.user.id)).then(result => {
154
- this.roles = result
155
- }).catch(error => {
156
- console.log(error)
157
- })
158
- },
159
-
160
- postRole(role) {
161
- this.http.post(this.url.lesli('users/:id/roles', this.user.id), {
162
- user_role: {
163
- id: role.id
164
- }
165
- }).then(result => {
166
- this.msg.success(I18n.t("core.users.messages_success_operation"))
167
- }).catch(error => {
168
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
169
- })
170
- },
171
-
172
- deleteRole(role) {
173
- this.http.delete(this.url.lesli('users/:user_id/roles/:role_id', {
174
- user_id: this.user.id,
175
- role_id: role.id
176
- })).then(result => {
177
- this.msg.success(I18n.t("core.users.messages_success_operation"))
178
- }).catch(error => {
179
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
180
- })
181
- },
182
-
183
- doRequestPassword() {
184
- this.http.post(this.url.lesli("users/:id/requestpassword", this.user.id)).then(result => {
185
- this.msg.success(I18n.t("core.users.messages_success_operation"))
186
- }).catch(error => {
187
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
188
- })
189
- },
190
-
191
- doPasswordReset() {
192
- this.http.post(this.url.lesli("users/:id/passwordreset", this.user.id)).then(result => {
193
- this.msg.success(I18n.t("core.users.messages_success_operation"))
194
- }).catch(error => {
195
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
196
- })
197
- },
198
-
199
- doLogout() {
200
- this.http.post(this.url.lesli("users/:id/logout", this.user.id)).then(result => {
201
- this.msg.success(I18n.t("core.users.messages_success_operation"))
202
- }).catch(error => {
203
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
204
- })
205
- },
206
-
207
- doRevokeAccess() {
208
- this.http.post(this.url.lesli("users/:id/revokeaccess", this.user.id)).then(result => {
209
- this.msg.success(I18n.t("core.users.messages_success_operation"))
210
- }).catch(error => {
211
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
212
- })
213
- },
214
-
215
- fetchSessions() {
216
- if (!this.sessions.length > 0) {
217
- this.getSessions()
218
- }
219
- },
220
-
221
- getSessions() {
222
- this.http.get(this.url.lesli("users/:id/sessions", this.user.id )).then(result => {
223
- this.sessions.pagination = result.pagination
224
- this.sessions.records = result.records
225
- }).catch(error => {
226
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
227
- }).finally(() => {
228
- this.loading = false
229
- })
230
- },
231
-
232
- deleteSession(user_session_id){
233
- this.dialog.confirmation({
234
- title: "Close session",
235
- text: 'Are you sure you want to close this session',
236
- confirmText: "Yes",
237
- cancelText: "No"
238
- })
239
- .then(({ isConfirmed }) => {
240
- if (isConfirmed) {
241
- this.http.delete(this.url.lesli("users/:id/sessions/:session_id", {
242
- id: this.user.id,
243
- session_id: user_session_id
244
- })).then(result => {
245
- this.msg.success(I18n.t("core.users.messages_success_operation"))
246
- }).catch(error => {
247
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
248
- })
249
- this.fetchSessions()
250
- }
251
- })
252
- },
253
-
254
- postLanguage() {
255
- this.http.post(this.url.lesli('users/:id/settings', this.user.id), {
256
- user_setting: {
257
- name: 'locale',
258
- value: this.user.locale.value
259
- }
260
- }).then(result => {
261
- this.msg.success(I18n.t("core.users.messages_success_operation"))
262
- // TODO: Only if current_user changed his own language
263
- // reload the page so the user can work with the new language
264
- // setTimeout(() => window.location.reload(), 1000)
265
- }).catch(error => {
266
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
267
- })
268
- },
269
-
270
- getOptions() {
271
- this.http.get(this.url.lesli("users/options")).then(result => {
272
- this.options.salutations = result.salutations
273
-
274
- this.options.locales = Object.keys(result.locales).map(key => {
275
- return {label: result.locales[key], value: key}
276
- })
277
- }).catch(error => {
278
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
279
- })
280
- },
281
- }
282
- })
283
-
284
-
285
-
286
-
287
- /*
288
-
289
-
290
-
291
- updatePassword() {
292
- this.http.put("/", {
293
- user: {
294
- password: this.user.password,
295
- password_confirmation: this.user.password_confirmation
296
- }
297
- }).then(result => {
298
- this.msg.success(I18n.t("core.users.messages_success_operation"))
299
- this.user.password = ""
300
- this.user.password_confirmation = ""
301
- }).catch(error => {
302
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
303
- })
304
- },
305
-
306
- // This action is used to change the user status active or inactive
307
- putUserStatus(){
308
- this.dialog.confirmation({
309
- title: "Change status",
310
- text: "Are you sure you want to change the status of this user?",
311
- confirmText: "Yes",
312
- cancelText: "No"
313
- })
314
- .then(({ isConfirmed }) => {
315
- if (isConfirmed) {
316
- this.http.patch(this.url.lesli('users/:id', this.user.id), {
317
- user: {
318
- active: this.user.active
319
- }
320
- }).then(result => {
321
- this.msg.success(I18n.t("core.users.messages_success_operation"))
322
- }) .catch(error => {
323
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
324
- })
325
- } else {
326
- this.user.active = !this.user.active
327
- }
328
- })
329
- },
330
-
331
- */
@@ -1,175 +0,0 @@
1
- /*
2
- Lesli
3
-
4
- Copyright (c) 2023, Lesli Technologies, S. A.
5
-
6
- This program is free software: you can redistribute it and/or modify
7
- it under the terms of the GNU General Public License as published by
8
- the Free Software Foundation, either version 3 of the License, or
9
- (at your option) any later version.
10
-
11
- This program is distributed in the hope that it will be useful,
12
- but WITHOUT ANY WARRANTY; without even the implied warranty of
13
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14
- GNU General Public License for more details.
15
-
16
- You should have received a copy of the GNU General Public License
17
- along with this program. If not, see http://www.gnu.org/licenses/.
18
-
19
- Lesli · Ruby on Rails Development Platform.
20
-
21
- Made with ♥ by https://www.lesli.tech
22
- Building a better future, one line of code at a time.
23
-
24
- @contact hello@lesli.tech
25
- @website https://www.lesli.tech
26
- @license GPLv3 http://www.gnu.org/licenses/gpl-3.0.en.html
27
-
28
- // · ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~ ~·~
29
- // ·
30
- */
31
-
32
-
33
- // ·
34
- import { defineStore } from "pinia"
35
-
36
- // · translations
37
- const translations = {
38
- core: {
39
- roles: I18n.t("core.roles"),
40
- users: I18n.t("core.users"),
41
- shared: I18n.t("core.shared")
42
- }
43
- }
44
-
45
- // ·
46
- export const useUsers = defineStore("administration.users", {
47
- state: () => {
48
- return {
49
- loading: false,
50
- search: "",
51
- list: [],
52
- order: {
53
- column: "id",
54
- direction: "desc"
55
- },
56
- index: {
57
- pagination: {},
58
- records: []
59
- },
60
- filters :{
61
- per_page: 15,
62
- role: null,
63
- status: 'active'
64
- },
65
- roles_options: [],
66
-
67
- user: {
68
- roles_id: null,
69
- email: null,
70
- first_name: null,
71
- last_name: null,
72
- telephone: null,
73
- }
74
- }
75
- },
76
- actions: {
77
-
78
- search(search_string) {
79
- this.index.pagination.page = 1
80
- this.search_string = search_string
81
- this.loading = true
82
- this.getUsers()
83
- },
84
-
85
- paginateIndex(page) {
86
- this.index.pagination.page = page
87
- this.getUsers()
88
- },
89
-
90
- sortIndex(column, direction) {
91
- this.order.column = column
92
- this.order.direction = direction
93
- this.getUsers()
94
- },
95
-
96
- fetchUsers() {
97
-
98
- if (!this.index.pagination?.results > 0) {
99
- this.loading = true
100
- this.getUsers()
101
- }
102
-
103
- },
104
-
105
- getUsers() {
106
-
107
- const query_filters = {}
108
-
109
- //Format filters to send them in the query string
110
- for (const [key, value] of Object.entries(this.filters)) {
111
- //query_filters[key] = [value]
112
- }
113
-
114
- this.http.get(
115
- this.url
116
- .admin("users")
117
- .search(this.search_string)
118
- .paginate(this.index.pagination.page, this.filters.per_page)
119
- .filter(query_filters)
120
- .order(this.order.column, this.order.direction)
121
- ).then(result => {
122
- this.index = result
123
- this.search_string=""
124
- }).catch(error => {
125
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
126
- }).finally(() => {
127
- this.loading = false
128
- })
129
- },
130
-
131
- getUser(id=null) {
132
-
133
- // get the profile by default
134
- let url = this.url.lesli("profile")
135
-
136
- // get an specifick user if id is provided
137
- if (id) { url = this.url.lesli("users/:id", id) }
138
-
139
- this.http.get(url).then(result => {
140
- this.user = result
141
- this.user.password = ""
142
- this.user.password_confirmation = ""
143
-
144
- this.language = result.locale ? result.locale.value : this.language
145
-
146
- // Backend should return the list of roles ordered by object level permission
147
- this.role_names = result.roles[0].name
148
-
149
- }).catch(error => {
150
- this.msg.danger(I18n.t("core.shared.messages_danger_internal_error"))
151
- }).finally(() => {
152
- this.loading = false
153
- })
154
- },
155
-
156
- postUsers() {
157
- return this.http.post(this.url.admin("users"), {
158
- user: this.user
159
- })
160
- },
161
-
162
- fetchList() {
163
- this.loading = true
164
- return this.http.get(this.url.admin("users/list")).then(response => {
165
- //this.records = response
166
- this.list = response
167
- }).catch(error => {
168
-
169
- }).finally(() => {
170
- this.loading = false
171
- })
172
- }
173
-
174
- }
175
- })