1
1
<template >
2
2
<v-container fluid class =" user-management-tab" >
3
- <h2 class =" text-h5 mb-4" >{{ $t('admin.userManagement.title') }}</h2 >
3
+
4
+ <v-btn color =" primary" class =" mt-4" @click =" openAddUserDialog" >
5
+ {{ $t('admin.userManagement.addUser') }}
6
+ </v-btn >
4
7
5
8
<v-data-table :headers =" headers" :items =" users" :items-per-page =" 5" class =" elevation-1" :load-children =" fetchUsers"
6
9
:items-per-page-text =" $t('common.itemsPerPageText')" >
7
10
<template #[` item.actions ` ]=" { item } " >
8
11
<v-icon size =" small" class =" me-2" @click =" openEditUserDialog(item)" >
9
12
mdi-pencil
10
13
</v-icon >
11
- <v-icon v-if =" item.username !== 'admin'" size =" small" @click =" deleteUser (item)" >
14
+ <v-icon v-if =" item.username !== 'admin'" size =" small" @click =" openDeleteConfirmDialog (item)" >
12
15
mdi-delete
13
16
</v-icon >
14
17
</template >
15
18
</v-data-table >
16
-
17
- <v-btn color =" primary" class =" mt-4" @click =" openAddUserDialog" >
18
- {{ $t('admin.userManagement.addUser') }}
19
- </v-btn >
20
19
<div >
21
20
<v-chip v-if =" error" color =" red darken-1" >{{ $t('common.error') }}</v-chip >
22
21
</div >
22
+ </v-container >
23
23
24
- <v-dialog v-model =" addUserDialog" max-width =" 500px" >
25
- <v-card >
26
- <v-card-title >{{ $t('admin.userManagement.addNewUser') }}</v-card-title >
27
- <v-card-text >
28
- <v-text-field v-model =" newUser.username" :label =" $t('admin.userManagement.username')" required ></v-text-field >
29
- <v-text-field v-model =" newUser.email" :label =" $t('admin.userManagement.email')" required
30
- type =" email" ></v-text-field >
31
- <v-text-field v-model =" newUser.password" :label =" $t('admin.userManagement.password')" required
32
- type =" password" ></v-text-field >
33
- <v-autocomplete v-model =" newUser.roles" :items =" roles" item-title =" name" outlined chips closable-chips
34
- small-chips :label =" $t('admin.userManagement.roles')" multiple ></v-autocomplete >
35
- </v-card-text >
36
- <v-card-actions >
37
- <v-spacer ></v-spacer >
38
- <v-btn color =" blue darken-1" text @click =" closeAddUserDialog" >{{ $t('common.cancel') }}</v-btn >
39
- <v-btn color =" blue darken-1" text @click =" createUser" >{{ $t('common.save') }}</v-btn >
40
- <v-chip v-if =" error" color =" red darken-1" >{{ $t('common.error') }}</v-chip >
41
- </v-card-actions >
42
- </v-card >
43
- </v-dialog >
44
24
45
- <v-dialog v-model =" editUserDialog" max-width =" 500px" >
46
- <v-card >
47
- <v-card-title >{{ $t('admin.userManagement.editUser') }}</v-card-title >
48
- <v-card-text >
49
- <v-text-field v-model =" editedUser.username" :label =" $t('admin.userManagement.username')"
50
- required ></v-text-field >
51
- <v-text-field v-model =" editedUser.email" :label =" $t('admin.userManagement.email')" required
52
- type =" email" ></v-text-field >
53
- <v-text-field v-model =" editedUser.password" :label =" $t('admin.userManagement.password')" required
54
- type =" password" ></v-text-field >
55
- <v-autocomplete v-model =" editedUser.roles" :items =" roles" item-title =" name" outlined chips closable-chips
56
- small-chips :label =" $t('admin.userManagement.roles')" multiple ></v-autocomplete >
57
- </v-card-text >
58
- <v-card-actions >
59
- <v-spacer > </v-spacer >
60
- <v-btn color =" blue darken-1" text @click =" closeEditUserDialog" >{{ $t('common.cancel') }}</v-btn >
61
- <v-btn color =" blue darken-1" text @click =" updateUser(editedUser)" >{{ $t('common.save') }}</v-btn >
62
- <v-chip v-if =" error" color =" red darken-1" >{{ $t('common.error') }}</v-chip >
63
- </v-card-actions >
64
- </v-card >
65
- </v-dialog >
66
- </v-container >
25
+ <v-dialog v-model =" addUserDialog" max-width =" 500px" >
26
+ <v-card >
27
+ <v-card-title >{{ $t('admin.userManagement.addNewUser') }}</v-card-title >
28
+ <v-card-text >
29
+ <v-text-field v-model =" newUser.username" :label =" $t('admin.userManagement.username')" required ></v-text-field >
30
+ <v-text-field v-model =" newUser.email" :label =" $t('admin.userManagement.email')" required
31
+ type =" email" ></v-text-field >
32
+ <v-text-field v-model =" newUser.password" :label =" $t('admin.userManagement.password')" required
33
+ type =" password" ></v-text-field >
34
+ <v-autocomplete v-model =" newUser.roles" :items =" roles" item-title =" name" outlined chips closable-chips
35
+ small-chips :label =" $t('admin.userManagement.roles')" multiple ></v-autocomplete >
36
+ </v-card-text >
37
+ <v-card-actions >
38
+ <v-spacer ></v-spacer >
39
+ <v-btn color =" blue darken-1" text @click =" closeAddUserDialog" >{{ $t('common.cancel') }}</v-btn >
40
+ <v-btn color =" blue darken-1" text @click =" createUser" >{{ $t('common.save') }}</v-btn >
41
+ <v-chip v-if =" error" color =" red darken-1" >{{ $t('common.error') }}</v-chip >
42
+ </v-card-actions >
43
+ </v-card >
44
+ </v-dialog >
45
+
46
+ <v-dialog v-model =" editUserDialog" max-width =" 500px" >
47
+ <v-card >
48
+ <v-card-title >{{ $t('admin.userManagement.editUser') }}</v-card-title >
49
+ <v-card-text >
50
+ <v-text-field v-model =" editedUser.username" :label =" $t('admin.userManagement.username')"
51
+ required ></v-text-field >
52
+ <v-text-field v-model =" editedUser.email" :label =" $t('admin.userManagement.email')" required
53
+ type =" email" ></v-text-field >
54
+ <v-text-field v-model =" editedUser.password" :label =" $t('admin.userManagement.password')" required
55
+ type =" password" ></v-text-field >
56
+ <v-autocomplete v-model =" editedUser.roles" :items =" roles" item-title =" name" outlined chips closable-chips
57
+ small-chips :label =" $t('admin.userManagement.roles')" multiple ></v-autocomplete >
58
+ </v-card-text >
59
+ <v-card-actions >
60
+ <v-spacer > </v-spacer >
61
+ <v-btn color =" blue darken-1" text @click =" closeEditUserDialog" >{{ $t('common.cancel') }}</v-btn >
62
+ <v-btn color =" blue darken-1" text @click =" updateUser(editedUser)" >{{ $t('common.save') }}</v-btn >
63
+ <v-chip v-if =" error" color =" red darken-1" >{{ $t('common.error') }}</v-chip >
64
+ </v-card-actions >
65
+ </v-card >
66
+ </v-dialog >
67
+
68
+ <v-dialog v-model =" deleteConfirmDialog" max-width =" 400px" >
69
+ <v-card >
70
+ <v-card-title >{{ $t('admin.userManagement.confirmDelete') }}</v-card-title >
71
+ <v-card-text >
72
+ {{ $t('admin.userManagement.deleteConfirmMessage') }}
73
+ </v-card-text >
74
+ <v-card-text >
75
+ {{ userToDelete.username }}
76
+ </v-card-text >
77
+ <v-card-actions >
78
+ <v-spacer ></v-spacer >
79
+ <v-btn color =" blue darken-1" text @click =" closeDeleteConfirmDialog" >{{ $t('common.cancel') }}</v-btn >
80
+ <v-btn color =" red darken-1" text @click =" deleteUser(userToDelete)" >{{ $t('common.delete') }}</v-btn >
81
+ </v-card-actions >
82
+ <v-chip v-if =" error" color =" red darken-1" >{{ $t('common.error') }}</v-chip >
83
+ </v-card >
84
+ </v-dialog >
85
+
67
86
</template >
68
87
69
88
<script setup>
70
- import { ref , computed , onMounted } from ' vue' ;
89
+ import { ref , computed , onMounted , onUnmounted } from ' vue' ;
71
90
import { useI18n } from ' vue-i18n' ;
72
91
73
92
onMounted (async () => {
74
93
await fetchUsers ();
75
94
await fetchRoles ();
95
+ document .documentElement .style .overflowY = ' scroll' ;
96
+ });
97
+
98
+ onUnmounted (async () => {
99
+ document .documentElement .style .overflowY = ' auto' ;
76
100
});
77
101
78
102
const { t } = useI18n ();
79
103
80
104
const headers = computed (() => [
105
+ { title: ' #' , key: ' id' },
81
106
{ title: t (' admin.userManagement.headers.username' ), align: ' start' , key: ' username' },
82
107
{ title: t (' admin.userManagement.headers.email' ), key: ' email' },
83
108
{ title: t (' admin.userManagement.headers.roles' ), key: ' rolesText' },
@@ -96,6 +121,21 @@ const newUser = ref({
96
121
roles: [],
97
122
});
98
123
124
+ const deleteConfirmDialog = ref (false );
125
+ const userToDelete = ref ({});
126
+
127
+ const openDeleteConfirmDialog = (user ) => {
128
+ error .value = false ;
129
+ userToDelete .value = user;
130
+ deleteConfirmDialog .value = true ;
131
+ };
132
+
133
+ const closeDeleteConfirmDialog = () => {
134
+ error .value = false ;
135
+ userToDelete .value = {};
136
+ deleteConfirmDialog .value = false ;
137
+ };
138
+
99
139
const openAddUserDialog = () => {
100
140
error .value = false ;
101
141
addUserDialog .value = true ;
@@ -107,7 +147,6 @@ const openAddUserDialog = () => {
107
147
};
108
148
109
149
const editUserDialog = ref (false );
110
-
111
150
const editedUser = ref ({
112
151
username: ' ' ,
113
152
email: ' ' ,
@@ -135,6 +174,7 @@ const closeEditUserDialog = () => {
135
174
};
136
175
137
176
const closeAddUserDialog = () => {
177
+ error .value = false ;
138
178
addUserDialog .value = false ;
139
179
newUser .value = {
140
180
username: ' ' ,
@@ -144,8 +184,10 @@ const closeAddUserDialog = () => {
144
184
};
145
185
146
186
const deleteUser = async (user ) => {
147
- // Implement delete user logic
148
- console .log (' Delete user:' , user);
187
+ error .value = false ;
188
+ if (user .username === " admin" ) {
189
+ return ;
190
+ }
149
191
return await fetch (" /Invoke/auth/deleteUser" , {
150
192
method: " post" ,
151
193
headers: {
@@ -160,6 +202,7 @@ const deleteUser = async (user) => {
160
202
.then ((res ) => res .json ())
161
203
.then ((json ) => {
162
204
fetchUsers (); // refreshes users
205
+ closeDeleteConfirmDialog ();
163
206
})
164
207
.catch ((err ) => { error .value = true ; console .warn (err); });
165
208
};
@@ -194,8 +237,9 @@ const fetchRoles = async () => {
194
237
195
238
const updateUser = async (user ) => {
196
239
error .value = false ;
240
+ if (user .value ) user = user .value ;
197
241
roleChange (user);
198
- var userDup = Object .assign ({}, user);
242
+ const userDup = Object .assign ({}, user);
199
243
delete userDup[" id" ];
200
244
delete userDup[" rolesText" ];
201
245
delete userDup[" roles" ];
@@ -213,8 +257,12 @@ const updateUser = async (user) => {
213
257
})
214
258
.then ((res ) => res .json ())
215
259
.then ((json ) => {
260
+ if (json .error === false ) {
261
+ closeEditUserDialog ();
262
+ } else {
263
+ error .value = true ;
264
+ }
216
265
fetchUsers (); // refreshes users
217
- closeEditUserDialog ();
218
266
})
219
267
.catch ((err ) => { error .value = true ; console .warn (err); });
220
268
}
@@ -239,6 +287,9 @@ const addRoleToUser = async (username, roleName) => {
239
287
}
240
288
241
289
const removeRoleFromUser = async (username , roleName ) => {
290
+ if (username === " admin" && roleName === " admin" ) {
291
+ return ;
292
+ }
242
293
return await fetch (" /Invoke/auth/userRemoveRole" , {
243
294
method: " post" ,
244
295
headers: {
@@ -258,15 +309,23 @@ const removeRoleFromUser = async (username, roleName) => {
258
309
}
259
310
260
311
const roleChange = (user ) => {
261
- for (let i = 0 ; i < user .roles .length ; i++ )
262
- if (! editedUserRoles .value .includes (user .roles [i]))
263
- addRoleToUser (user .username , user .roles [i]);
264
- for (let i = 0 ; i < editedUserRoles .value .length ; i++ )
265
- if (! user .roles .includes (editedUserRoles .value [i]))
266
- removeRoleFromUser (user .username , editedUserRoles .value [i]);
312
+ for (let i = 0 ; i < user .roles .length ; i++ ) {
313
+ const roleName = user .roles [i]? .name || user .roles [i];
314
+ if (! editedUserRoles .value .includes (roleName))
315
+ addRoleToUser (user .username , roleName);
316
+ }
317
+
318
+ for (let i = 0 ; i < editedUserRoles .value .length ; i++ ) {
319
+ const roleName = editedUserRoles .value [i]? .name || editedUserRoles .value [i];
320
+ if (! user .roles .includes (roleName))
321
+ removeRoleFromUser (user .username , roleName);
322
+ }
267
323
}
268
324
269
325
const createUser = async () => {
326
+ if (newUser .value .username === " admin" ) {
327
+ return ;
328
+ }
270
329
return await fetch (" /Invoke/auth/createUser" , {
271
330
method: " post" ,
272
331
headers: {
@@ -277,15 +336,19 @@ const createUser = async () => {
277
336
})
278
337
.then ((res ) => res .json ())
279
338
.then (async (json ) => {
280
- await fetchUsers (); // refreshes users
281
- for (let i = 0 ; i < users .value .length ; i++ ) {
282
- if (users .value [i].username === newUser .value .username ) {
283
- newUser .value ._id = users .value [i]._id ;
284
- await updateUser (newUser .value );
285
- break ;
339
+ if (json .error === false ) {
340
+ await fetchUsers (); // refreshes users
341
+ for (let i = 0 ; i < users .value .length ; i++ ) {
342
+ if (users .value [i].username === newUser .value .username ) {
343
+ newUser .value ._id = users .value [i]._id ;
344
+ await updateUser (newUser);
345
+ break ;
346
+ }
286
347
}
348
+ closeAddUserDialog ();
349
+ } else {
350
+ error .value = true ;
287
351
}
288
- closeAddUserDialog ();
289
352
})
290
353
.catch ((err ) => { error .value = true ; console .warn (err); });
291
354
}
0 commit comments