@igea/oac_frontend 1.0.16 → 1.0.18
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.
- package/package.json +1 -1
- package/src/locales/en.json +19 -2
- package/src/locales/it.json +19 -2
- package/src/models/DataModel +4 -2
- package/src/public/css/style.css +9 -2
- package/src/public/js/app/vue-users-edit.js +68 -8
- package/src/public/js/app/vue-users-manage.js +14 -3
- package/src/views/sidebar.twig +28 -16
- package/src/views/users/edit.twig +41 -27
- package/src/views/users/manage.twig +2 -0
package/package.json
CHANGED
package/src/locales/en.json
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"role": "Role",
|
|
18
18
|
"edit": "Edit",
|
|
19
19
|
"delete": "Delete",
|
|
20
|
-
"new": "New"
|
|
20
|
+
"new": "New",
|
|
21
|
+
"confirm_delete": "Are you sure you want to delete this user?"
|
|
21
22
|
},
|
|
22
23
|
"edit": {
|
|
23
24
|
"title": "User",
|
|
@@ -26,7 +27,14 @@
|
|
|
26
27
|
"password": "Password",
|
|
27
28
|
"confirm_password": "Confirm password",
|
|
28
29
|
"save": "Save",
|
|
29
|
-
"cancel": "Cancel"
|
|
30
|
+
"cancel": "Cancel",
|
|
31
|
+
"invalid_name": "Invalid name",
|
|
32
|
+
"invalid_surname": "Invalid surname",
|
|
33
|
+
"invalid_username": "Invalid username",
|
|
34
|
+
"invalid_email": "Invalid email address",
|
|
35
|
+
"invalid_password": "Invalid password (must be at least 6 characters)",
|
|
36
|
+
"different_password": "Passwords do not match",
|
|
37
|
+
"save_ok": "Data saved successfully"
|
|
30
38
|
},
|
|
31
39
|
"profile": {
|
|
32
40
|
"title": "Profile"
|
|
@@ -37,5 +45,14 @@
|
|
|
37
45
|
"editor": "Editor",
|
|
38
46
|
"reader": "Reader"
|
|
39
47
|
}
|
|
48
|
+
},
|
|
49
|
+
"search": {
|
|
50
|
+
"fast": {
|
|
51
|
+
"title": "Fast search"
|
|
52
|
+
},
|
|
53
|
+
"advanced": {
|
|
54
|
+
"title": "Advanced search"
|
|
55
|
+
}
|
|
56
|
+
|
|
40
57
|
}
|
|
41
58
|
}
|
package/src/locales/it.json
CHANGED
|
@@ -17,7 +17,8 @@
|
|
|
17
17
|
"role": "Ruolo",
|
|
18
18
|
"edit": "Modifica",
|
|
19
19
|
"delete": "Elimina",
|
|
20
|
-
"new": "Nuovo"
|
|
20
|
+
"new": "Nuovo",
|
|
21
|
+
"confirm_delete": "Sei sicuro di voler eliminare questo utente?"
|
|
21
22
|
},
|
|
22
23
|
"edit": {
|
|
23
24
|
"title": "Utente",
|
|
@@ -26,7 +27,14 @@
|
|
|
26
27
|
"password": "Password",
|
|
27
28
|
"confirm_password": "Conferma password",
|
|
28
29
|
"save": "Salva",
|
|
29
|
-
"cancel": "Annulla"
|
|
30
|
+
"cancel": "Annulla",
|
|
31
|
+
"invalid_name": "Nome non valido",
|
|
32
|
+
"invalid_surname": "Cognome non valido",
|
|
33
|
+
"invalid_username": "Nome utente non valido",
|
|
34
|
+
"invalid_email": "Indirizzo email non valido",
|
|
35
|
+
"invalid_password": "Password non valida (deve contenere almeno 6 caratteri)",
|
|
36
|
+
"different_password": "Le password non corrispondono",
|
|
37
|
+
"save_ok": "Salvataggio dati eseguito correttamente"
|
|
30
38
|
},
|
|
31
39
|
"profile": {
|
|
32
40
|
"title": "Profilo"
|
|
@@ -37,5 +45,14 @@
|
|
|
37
45
|
"editor": "Editore",
|
|
38
46
|
"reader": "Lettore"
|
|
39
47
|
}
|
|
48
|
+
},
|
|
49
|
+
"search": {
|
|
50
|
+
"fast": {
|
|
51
|
+
"title": "Ricerca veloce"
|
|
52
|
+
},
|
|
53
|
+
"advanced": {
|
|
54
|
+
"title": "Ricerca avanzata"
|
|
55
|
+
}
|
|
56
|
+
|
|
40
57
|
}
|
|
41
58
|
}
|
package/src/models/DataModel
CHANGED
package/src/public/css/style.css
CHANGED
|
@@ -31,7 +31,7 @@ html, body {
|
|
|
31
31
|
display: flex;
|
|
32
32
|
margin-top: 100px;
|
|
33
33
|
margin-bottom: 80px;
|
|
34
|
-
min-height: calc(100vh
|
|
34
|
+
min-height: calc(100vh + 150px);
|
|
35
35
|
overflow: auto;
|
|
36
36
|
}
|
|
37
37
|
|
|
@@ -71,11 +71,18 @@ html, body {
|
|
|
71
71
|
border-radius: 8px;
|
|
72
72
|
}
|
|
73
73
|
|
|
74
|
-
|
|
75
74
|
.main-content {
|
|
76
75
|
flex: 1;
|
|
77
76
|
padding: 1em;
|
|
78
77
|
overflow-y: auto;
|
|
79
78
|
}
|
|
80
79
|
|
|
80
|
+
.warning {
|
|
81
|
+
background: #f8d7da;
|
|
82
|
+
color: #721c24;
|
|
83
|
+
padding: 5px;
|
|
84
|
+
border-radius: 5px;
|
|
85
|
+
margin-bottom: 20px;
|
|
86
|
+
}
|
|
87
|
+
|
|
81
88
|
/*# sourceMappingURL=style.css.map */
|
|
@@ -15,41 +15,101 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
15
15
|
role_admin: el.dataset.role_admin,
|
|
16
16
|
role_editor: el.dataset.role_editor,
|
|
17
17
|
role_reader: el.dataset.role_reader,
|
|
18
|
+
save_ok: el.dataset.save_ok
|
|
18
19
|
},
|
|
19
20
|
user: {
|
|
21
|
+
id: parseInt(el.dataset.user_id) || 0,
|
|
20
22
|
name: "",
|
|
21
23
|
surname: "",
|
|
22
24
|
username: "",
|
|
23
25
|
email: "",
|
|
26
|
+
mobile: "",
|
|
24
27
|
password: "",
|
|
25
28
|
confirm_password: "",
|
|
26
29
|
role: 2
|
|
27
|
-
}
|
|
30
|
+
}
|
|
28
31
|
}
|
|
29
32
|
},
|
|
30
33
|
mounted() {
|
|
31
34
|
this.getUser();
|
|
32
35
|
},
|
|
36
|
+
computed:{
|
|
37
|
+
validator(){
|
|
38
|
+
let name = this.user.name.length > 0;
|
|
39
|
+
let surname = this.user.surname.length > 0;
|
|
40
|
+
let username = this.user.username.length > 0;
|
|
41
|
+
let email = this.user.email.length > 0 && this.user.email.includes("@");
|
|
42
|
+
let password = this.user.password.length >= 6 || (this.user.id > 0 && this.user.password.length == 0);
|
|
43
|
+
let confirm_password = this.user.password == this.user.confirm_password;
|
|
44
|
+
return {
|
|
45
|
+
name: name,
|
|
46
|
+
surname: surname,
|
|
47
|
+
username: username,
|
|
48
|
+
email: email,
|
|
49
|
+
password: password,
|
|
50
|
+
confirm_password: confirm_password
|
|
51
|
+
}
|
|
52
|
+
},
|
|
53
|
+
validForm(){
|
|
54
|
+
return this.validator.name && this.validator.surname && this.validator.username && this.validator.email && this.validator.password && this.validator.confirm_password;
|
|
55
|
+
}
|
|
56
|
+
},
|
|
33
57
|
methods: {
|
|
34
58
|
getUser() {
|
|
35
|
-
|
|
36
|
-
axios.get("/backend/users/").then(response => {
|
|
59
|
+
if(this.user.id == 0) return;
|
|
60
|
+
axios.get("/backend/users/" + this.user.id).then(response => {
|
|
37
61
|
var data = response.data;
|
|
38
62
|
if(data.success) {
|
|
39
|
-
this.
|
|
63
|
+
this.user = data.data;
|
|
64
|
+
this.user.password = "";
|
|
65
|
+
this.user.confirm_password = "";
|
|
40
66
|
} else {
|
|
41
|
-
console.error("Failed to fetch
|
|
67
|
+
console.error("Failed to fetch user:", data.message);
|
|
42
68
|
}
|
|
43
69
|
}).catch(error => {
|
|
44
70
|
console.log(error);
|
|
45
71
|
});
|
|
46
|
-
*/
|
|
47
72
|
},
|
|
48
73
|
save() {
|
|
49
|
-
|
|
74
|
+
if(!this.validForm) return;
|
|
75
|
+
let payload = {
|
|
76
|
+
id: this.user.id,
|
|
77
|
+
name: this.user.name,
|
|
78
|
+
surname: this.user.surname,
|
|
79
|
+
username: this.user.username,
|
|
80
|
+
email: this.user.email,
|
|
81
|
+
mobile: this.user.mobile,
|
|
82
|
+
role: this.user.role
|
|
83
|
+
};
|
|
84
|
+
if(this.user.password.length > 0)
|
|
85
|
+
payload["password"] = this.user.password;
|
|
86
|
+
let request;
|
|
87
|
+
if(this.user.id == 0) {
|
|
88
|
+
delete payload["id"];
|
|
89
|
+
request = axios.post("/backend/users", payload);
|
|
90
|
+
} else {
|
|
91
|
+
request = axios.put("/backend/users/" + this.user.id, payload);
|
|
92
|
+
}
|
|
93
|
+
request.then(response => {
|
|
94
|
+
var data = response.data;
|
|
95
|
+
if(data.success) {
|
|
96
|
+
alert(this.labels.save_ok);
|
|
97
|
+
if(document.referrer)
|
|
98
|
+
window.location.href = document.referrer;
|
|
99
|
+
else
|
|
100
|
+
window.history.back();
|
|
101
|
+
} else {
|
|
102
|
+
alert(data.message);
|
|
103
|
+
}
|
|
104
|
+
}).catch(error => {
|
|
105
|
+
alert(error);
|
|
106
|
+
});
|
|
50
107
|
},
|
|
51
108
|
cancel() {
|
|
52
|
-
|
|
109
|
+
if(document.referrer)
|
|
110
|
+
window.location.href = document.referrer;
|
|
111
|
+
else
|
|
112
|
+
window.history.back();
|
|
53
113
|
}
|
|
54
114
|
}
|
|
55
115
|
});
|
|
@@ -11,11 +11,13 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
11
11
|
return {
|
|
12
12
|
root: el.dataset.root,
|
|
13
13
|
cur_id: parseInt(el.dataset.cur_id) || 0,
|
|
14
|
+
cur_role: parseInt(el.dataset.cur_role),
|
|
14
15
|
labels: {
|
|
15
16
|
role_sudo: el.dataset.role_sudo,
|
|
16
17
|
role_admin: el.dataset.role_admin,
|
|
17
18
|
role_editor: el.dataset.role_editor,
|
|
18
19
|
role_reader: el.dataset.role_reader,
|
|
20
|
+
confirm_delete: el.dataset.confirm_delete
|
|
19
21
|
},
|
|
20
22
|
users: []
|
|
21
23
|
}
|
|
@@ -28,7 +30,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
28
30
|
axios.get("/backend/users/").then(response => {
|
|
29
31
|
var data = response.data;
|
|
30
32
|
if(data.success) {
|
|
31
|
-
this.users = data.data;
|
|
33
|
+
this.users = data.data.filter(u => u.role != 0 || this.cur_role == 0);
|
|
32
34
|
} else {
|
|
33
35
|
console.error("Failed to fetch users:", data.message);
|
|
34
36
|
}
|
|
@@ -45,8 +47,17 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
45
47
|
return label;
|
|
46
48
|
},
|
|
47
49
|
deleteUser(userId) {
|
|
48
|
-
|
|
49
|
-
|
|
50
|
+
if(!confirm(this.labels.confirm_delete)) return;
|
|
51
|
+
axios.delete("/backend/users/" + userId).then(response => {
|
|
52
|
+
var data = response.data;
|
|
53
|
+
if(data.success) {
|
|
54
|
+
this.users = this.users.filter(user => user.id !== userId);
|
|
55
|
+
} else {
|
|
56
|
+
console.error("Failed to fetch user:", data.message);
|
|
57
|
+
}
|
|
58
|
+
}).catch(error => {
|
|
59
|
+
console.log(error);
|
|
60
|
+
});
|
|
50
61
|
},
|
|
51
62
|
editUser(userId) {
|
|
52
63
|
window.location.href = `/${this.root}/users/${userId}`;
|
package/src/views/sidebar.twig
CHANGED
|
@@ -1,24 +1,36 @@
|
|
|
1
1
|
{% block sidebar %}
|
|
2
|
-
|
|
3
|
-
{% if user.id > 0 %}
|
|
4
|
-
|
|
5
|
-
<!-- abilitare solo per utenti ADMIN -->
|
|
6
|
-
{% if cur_role != "admin" %}
|
|
7
|
-
<div class="menu-item">
|
|
8
|
-
<a href="/{{ root }}/users/manage">
|
|
9
|
-
<i class="fa-solid fa-users-between-lines"></i>
|
|
10
|
-
<span>{{ t('users.manage.title') }}</span>
|
|
11
|
-
</a>
|
|
12
|
-
</div>
|
|
13
|
-
{% endif %}
|
|
14
2
|
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
3
|
+
<!-- abilitare solo per utenti ADMIN -->
|
|
4
|
+
{% if user.role == 0 or user.role == 1 %}
|
|
5
|
+
<div class="menu-item">
|
|
6
|
+
<a href="/{{ root }}/users/manage">
|
|
7
|
+
<i class="fa-solid fa-users-between-lines"></i>
|
|
8
|
+
<span>{{ t('users.manage.title') }}</span>
|
|
19
9
|
</a>
|
|
20
10
|
</div>
|
|
11
|
+
{% endif %}
|
|
21
12
|
|
|
13
|
+
{% if user.id > 0 %}
|
|
14
|
+
<div class="menu-item">
|
|
15
|
+
<a href="/{{ root }}/users/{{ cur_id }}">
|
|
16
|
+
<i class="fa-solid fa-id-badge"></i>
|
|
17
|
+
{{ t('users.profile.title') }}
|
|
18
|
+
</a>
|
|
19
|
+
</div>
|
|
22
20
|
{% endif %}
|
|
23
21
|
|
|
22
|
+
<div class="menu-item">
|
|
23
|
+
<a href="/{{ root }}/search/fast">
|
|
24
|
+
<i class="fa-solid fa-magnifying-glass"></i>
|
|
25
|
+
{{ t('search.fast.title') }}
|
|
26
|
+
</a>
|
|
27
|
+
</div>
|
|
28
|
+
|
|
29
|
+
<div class="menu-item">
|
|
30
|
+
<a href="/{{ root }}/search/advanced">
|
|
31
|
+
<i class="fa-solid fa-magnifying-glass-dollar"></i>
|
|
32
|
+
{{ t('search.advanced.title') }}
|
|
33
|
+
</a>
|
|
34
|
+
</div>
|
|
35
|
+
|
|
24
36
|
{% endblock %}
|
|
@@ -12,7 +12,9 @@
|
|
|
12
12
|
data-role_sudo="{{ t('users.role.sudo') }}"
|
|
13
13
|
data-role_admin="{{ t('users.role.admin') }}"
|
|
14
14
|
data-role_editor="{{ t('users.role.editor') }}"
|
|
15
|
-
data-role_reader="{{ t('users.role.reader') }}"
|
|
15
|
+
data-role_reader="{{ t('users.role.reader') }}"
|
|
16
|
+
data-user_id = "{{ id }}"
|
|
17
|
+
data-save_ok="{{ t('users.edit.save_ok') }}"
|
|
16
18
|
>
|
|
17
19
|
<h2 style="display:flex; justify-content:space-between; align-items:center;">
|
|
18
20
|
{% if id == 0 %}
|
|
@@ -27,55 +29,67 @@
|
|
|
27
29
|
|
|
28
30
|
<!-- Name -->
|
|
29
31
|
<div class="col-md-6">
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
32
|
+
<label for="name" class="form-label">{{ t('users.manage.name') }}:</label>
|
|
33
|
+
<input v-model="user.name" type="text" class="form-control" id="name" placeholder="">
|
|
34
|
+
<div v-if="!validator.name" id="nameHelp" class="form-text warning">
|
|
35
|
+
<i class="fa-solid fa-circle-exclamation"></i>
|
|
36
|
+
{{ t('users.edit.invalid_name') }}
|
|
37
|
+
</div>
|
|
33
38
|
</div>
|
|
34
39
|
|
|
35
40
|
<!-- Surname -->
|
|
36
41
|
<div class="col-md-6">
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
42
|
+
<label for="surname" class="form-label">{{ t('users.manage.surname') }}:</label>
|
|
43
|
+
<input v-model="user.surname" type="text" class="form-control" id="surname" placeholder="">
|
|
44
|
+
<div v-if="!validator.surname" id="surnameHelp" class="form-text warning">
|
|
45
|
+
<i class="fa-solid fa-circle-exclamation"></i>
|
|
46
|
+
{{ t('users.edit.invalid_surname') }}
|
|
47
|
+
</div>
|
|
40
48
|
</div>
|
|
41
49
|
|
|
42
50
|
<!-- Username -->
|
|
43
51
|
<div class="col-md-6">
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
52
|
+
<label for="username" class="form-label">{{ t('users.manage.username') }}:</label>
|
|
53
|
+
<input v-model="user.username" type="text" class="form-control" id="username" placeholder="">
|
|
54
|
+
<div v-if="!validator.username" id="usernameHelp" class="form-text warning">
|
|
55
|
+
<i class="fa-solid fa-circle-exclamation"></i>
|
|
56
|
+
{{ t('users.edit.invalid_username') }}
|
|
57
|
+
</div>
|
|
47
58
|
</div>
|
|
48
59
|
|
|
49
60
|
<!-- Email -->
|
|
50
61
|
<div class="col-md-6">
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
62
|
+
<label for="email" class="form-label">{{ t('users.manage.email') }}:</label>
|
|
63
|
+
<input v-model="user.email" type="email" class="form-control" id="email" placeholder="">
|
|
64
|
+
<div v-if="!validator.email" id="emailHelp" class="form-text warning">
|
|
65
|
+
<i class="fa-solid fa-circle-exclamation"></i>
|
|
66
|
+
{{ t('users.edit.invalid_email') }}
|
|
67
|
+
</div>
|
|
56
68
|
</div>
|
|
57
69
|
|
|
58
70
|
<!-- Password -->
|
|
59
71
|
<div class="col-md-6">
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
<label for="password" class="form-label">{{ t('users.edit.password') }}:</label>
|
|
73
|
+
<input v-model="user.password" type="password" class="form-control" id="password" placeholder="">
|
|
74
|
+
<div v-if="!validator.password" id="passwordHelp" class="form-text warning">
|
|
75
|
+
<i class="fa-solid fa-circle-exclamation"></i>
|
|
76
|
+
{{ t('users.edit.invalid_password') }}
|
|
77
|
+
</div>
|
|
65
78
|
</div>
|
|
66
79
|
|
|
67
80
|
<!-- Confirm Password -->
|
|
68
81
|
<div class="col-md-6">
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
82
|
+
<label for="password2" class="form-label">{{ t('users.edit.confirm_password') }}:</label>
|
|
83
|
+
<input v-model="user.confirm_password" type="password" class="form-control" id="password2" placeholder="">
|
|
84
|
+
<div v-if="!validator.confirm_password" id="password2Help" class="form-text warning">
|
|
85
|
+
<i class="fa-solid fa-circle-exclamation"></i>
|
|
86
|
+
{{ t('users.edit.different_password') }}
|
|
87
|
+
</div>
|
|
74
88
|
</div>
|
|
75
89
|
|
|
76
90
|
<!-- Role -->
|
|
77
91
|
<div class="col-md-6">
|
|
78
|
-
<label for="role" class="form-label">
|
|
92
|
+
<label for="role" class="form-label">{{ t('users.manage.role') }}:</label>
|
|
79
93
|
<select v-model.number="user.role" id="role" class="form-select">
|
|
80
94
|
<option :value="0">{{ t('users.role.sudo') }}</option>
|
|
81
95
|
<option :value="1">{{ t('users.role.admin') }}</option>
|
|
@@ -85,7 +99,7 @@
|
|
|
85
99
|
</div>
|
|
86
100
|
|
|
87
101
|
<!-- Buttons -->
|
|
88
|
-
<div class="col-12 text-center mt-4">
|
|
102
|
+
<div v-if="validForm" class="col-12 text-center mt-4">
|
|
89
103
|
<button @click="save()" type="submit" class="btn btn-primary me-2">{{ t('users.edit.save') }}</button>
|
|
90
104
|
<button @click="cancel()" type="button" class="btn btn-secondary">{{ t('users.edit.cancel') }}</button>
|
|
91
105
|
</div>
|
|
@@ -14,7 +14,9 @@
|
|
|
14
14
|
data-role_admin="{{ t('users.role.admin') }}"
|
|
15
15
|
data-role_editor="{{ t('users.role.editor') }}"
|
|
16
16
|
data-role_reader="{{ t('users.role.reader') }}"
|
|
17
|
+
data-confirm_delete="{{ t('users.manage.confirm_delete') }}"
|
|
17
18
|
data-cur_id="{{ cur_id }}"
|
|
19
|
+
data-cur_role="{{ user.role }}"
|
|
18
20
|
>
|
|
19
21
|
<h2 style="display:flex; justify-content:space-between; align-items:center;">
|
|
20
22
|
<span>{{ t('users.manage.title') }}</span>
|