@igea/oac_frontend 1.0.13 → 1.0.15
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 +2 -2
- package/src/controllers/users.js +10 -9
- package/src/index.js +2 -1
- package/src/locales/en.json +9 -0
- package/src/locales/it.json +9 -0
- package/src/models/DataModel +19 -0
- package/src/public/js/app/vue-users-edit.js +49 -0
- package/src/public/js/app/vue-users-manage.js +5 -1
- package/src/views/home.twig +0 -2
- package/src/views/sidebar.twig +20 -13
- package/src/views/users/edit.twig +98 -0
- package/src/views/users/manage.twig +41 -35
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@igea/oac_frontend",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.15",
|
|
4
4
|
"description": "Frontend service for the OAC project",
|
|
5
5
|
"main": "src/index.js",
|
|
6
6
|
"scripts": {
|
|
@@ -20,7 +20,7 @@
|
|
|
20
20
|
},
|
|
21
21
|
"homepage": "https://github.com/chpigea/oac_frontend#readme",
|
|
22
22
|
"dependencies": {
|
|
23
|
-
"@igea/oac_jwt_helpers": "1.0.
|
|
23
|
+
"@igea/oac_jwt_helpers": "1.0.10",
|
|
24
24
|
"axios": "1.10.0",
|
|
25
25
|
"cookie-parser": "1.4.7",
|
|
26
26
|
"express": "5.1.0",
|
package/src/controllers/users.js
CHANGED
|
@@ -1,28 +1,29 @@
|
|
|
1
1
|
const express = require('express');
|
|
2
2
|
const router = express.Router();
|
|
3
|
-
|
|
3
|
+
const DataModel = require('../models/DataModel');
|
|
4
4
|
|
|
5
5
|
module.exports = function(serviceName) {
|
|
6
6
|
/**
|
|
7
7
|
* @route GET /users/manage: redirect to the users page with list of users
|
|
8
8
|
*/
|
|
9
9
|
router.get('/manage', (req, res) => {
|
|
10
|
-
|
|
10
|
+
let data = new DataModel(req, {
|
|
11
11
|
root: serviceName,
|
|
12
12
|
title: 'User Management',
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
{ id: 2, name: 'bob', role: 'user' },
|
|
16
|
-
{ id: 3, name: 'charlie', role: 'user' },
|
|
17
|
-
]
|
|
18
|
-
});
|
|
13
|
+
});
|
|
14
|
+
res.render('users/manage.twig', data.toJson());
|
|
19
15
|
});
|
|
20
16
|
|
|
21
17
|
/**
|
|
22
18
|
* @route GET /users/:id: redirect to the user page with user details
|
|
23
19
|
*/
|
|
24
20
|
router.get('/:id', (req, res) => {
|
|
25
|
-
|
|
21
|
+
let data = new DataModel(req, {
|
|
22
|
+
root: serviceName,
|
|
23
|
+
title: 'User Edit',
|
|
24
|
+
id: req.params.id
|
|
25
|
+
});
|
|
26
|
+
res.render('users/edit.twig', data.toJson());
|
|
26
27
|
});
|
|
27
28
|
|
|
28
29
|
/**
|
package/src/index.js
CHANGED
|
@@ -78,7 +78,8 @@ getPort.default({
|
|
|
78
78
|
res.render('login', { root: serviceName, title: 'Login' });
|
|
79
79
|
});
|
|
80
80
|
app.get(`/${serviceName}/home`, (req, res) => {
|
|
81
|
-
|
|
81
|
+
let user = req.user;
|
|
82
|
+
res.render('home', { root: serviceName, title: 'Login', cur_id: user.id || 0 });
|
|
82
83
|
});
|
|
83
84
|
// ---------------------------------------------------------------------
|
|
84
85
|
// Start listing on the specified port
|
package/src/locales/en.json
CHANGED
|
@@ -19,6 +19,15 @@
|
|
|
19
19
|
"delete": "Delete",
|
|
20
20
|
"new": "New"
|
|
21
21
|
},
|
|
22
|
+
"edit": {
|
|
23
|
+
"title": "User",
|
|
24
|
+
"update": "Update",
|
|
25
|
+
"new": "New",
|
|
26
|
+
"password": "Password",
|
|
27
|
+
"confirm_password": "Confirm password",
|
|
28
|
+
"save": "Save",
|
|
29
|
+
"cancel": "Cancel"
|
|
30
|
+
},
|
|
22
31
|
"profile": {
|
|
23
32
|
"title": "Profile"
|
|
24
33
|
},
|
package/src/locales/it.json
CHANGED
|
@@ -19,6 +19,15 @@
|
|
|
19
19
|
"delete": "Elimina",
|
|
20
20
|
"new": "Nuovo"
|
|
21
21
|
},
|
|
22
|
+
"edit": {
|
|
23
|
+
"title": "Utente",
|
|
24
|
+
"update": "Modifica",
|
|
25
|
+
"new": "Nuovo",
|
|
26
|
+
"password": "Password",
|
|
27
|
+
"confirm_password": "Conferma password",
|
|
28
|
+
"save": "Salva",
|
|
29
|
+
"cancel": "Annulla"
|
|
30
|
+
},
|
|
22
31
|
"profile": {
|
|
23
32
|
"title": "Profilo"
|
|
24
33
|
},
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
|
|
2
|
+
class DataModel {
|
|
3
|
+
|
|
4
|
+
constructor(req, options = {}){
|
|
5
|
+
this.user = req.user || {};
|
|
6
|
+
this.options = options;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
toJson(){
|
|
10
|
+
return {
|
|
11
|
+
user: this.user,
|
|
12
|
+
cur_id: this.user.id || 0,
|
|
13
|
+
...this.options
|
|
14
|
+
};
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
module.exports = DataModel;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
const {createApp} = Vue;
|
|
2
|
+
|
|
3
|
+
const elementId = 'edit-user';
|
|
4
|
+
|
|
5
|
+
document.addEventListener('DOMContentLoaded', () => {
|
|
6
|
+
const el = document.getElementById(elementId);
|
|
7
|
+
|
|
8
|
+
const app = createApp({
|
|
9
|
+
delimiters: ['{%', '%}'],
|
|
10
|
+
data() {
|
|
11
|
+
return {
|
|
12
|
+
root: el.dataset.root,
|
|
13
|
+
labels: {
|
|
14
|
+
role_sudo: el.dataset.role_sudo,
|
|
15
|
+
role_admin: el.dataset.role_admin,
|
|
16
|
+
role_editor: el.dataset.role_editor,
|
|
17
|
+
role_reader: el.dataset.role_reader,
|
|
18
|
+
},
|
|
19
|
+
user: {}
|
|
20
|
+
}
|
|
21
|
+
},
|
|
22
|
+
mounted() {
|
|
23
|
+
this.getUser();
|
|
24
|
+
},
|
|
25
|
+
methods: {
|
|
26
|
+
getUser() {
|
|
27
|
+
/*
|
|
28
|
+
axios.get("/backend/users/").then(response => {
|
|
29
|
+
var data = response.data;
|
|
30
|
+
if(data.success) {
|
|
31
|
+
this.users = data.data;
|
|
32
|
+
} else {
|
|
33
|
+
console.error("Failed to fetch users:", data.message);
|
|
34
|
+
}
|
|
35
|
+
}).catch(error => {
|
|
36
|
+
console.log(error);
|
|
37
|
+
});
|
|
38
|
+
*/
|
|
39
|
+
},
|
|
40
|
+
save() {
|
|
41
|
+
// Here you would also make an API call to save the user to the server
|
|
42
|
+
},
|
|
43
|
+
cancel() {
|
|
44
|
+
window.history.back();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
app.mount(`#${elementId}`);
|
|
49
|
+
});
|
|
@@ -10,6 +10,7 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
10
10
|
data() {
|
|
11
11
|
return {
|
|
12
12
|
root: el.dataset.root,
|
|
13
|
+
cur_id: parseInt(el.dataset.cur_id) || 0,
|
|
13
14
|
labels: {
|
|
14
15
|
role_sudo: el.dataset.role_sudo,
|
|
15
16
|
role_admin: el.dataset.role_admin,
|
|
@@ -48,7 +49,10 @@ document.addEventListener('DOMContentLoaded', () => {
|
|
|
48
49
|
this.users = this.users.filter(user => user.id !== userId);
|
|
49
50
|
},
|
|
50
51
|
editUser(userId) {
|
|
51
|
-
window.location.href = `/${this.root}/users
|
|
52
|
+
window.location.href = `/${this.root}/users/${userId}`;
|
|
53
|
+
},
|
|
54
|
+
newUser() {
|
|
55
|
+
window.location.href = `/${this.root}/users/0`;
|
|
52
56
|
}
|
|
53
57
|
}
|
|
54
58
|
});
|
package/src/views/home.twig
CHANGED
package/src/views/sidebar.twig
CHANGED
|
@@ -1,17 +1,24 @@
|
|
|
1
1
|
{% block sidebar %}
|
|
2
2
|
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
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
|
+
|
|
15
|
+
<div class="menu-item">
|
|
16
|
+
<a href="/{{ root }}/users/{{ cur_id }}">
|
|
17
|
+
<i class="fa-solid fa-id-badge"></i>
|
|
18
|
+
{{ t('users.profile.title') }}
|
|
19
|
+
</a>
|
|
20
|
+
</div>
|
|
21
|
+
|
|
22
|
+
{% endif %}
|
|
9
23
|
|
|
10
|
-
<div class="menu-item">
|
|
11
|
-
<a href="/{{ root }}/users/profile">
|
|
12
|
-
<i class="fa-solid fa-id-badge"></i>
|
|
13
|
-
{{ t('users.profile.title') }}
|
|
14
|
-
</a>
|
|
15
|
-
</div>
|
|
16
|
-
|
|
17
24
|
{% endblock %}
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
{% set showSidebar = true %}
|
|
2
|
+
{% extends "../base.twig" %}
|
|
3
|
+
|
|
4
|
+
{% block extendHead %}
|
|
5
|
+
<script src="/{{ root }}/js/app/vue-users-edit.js"></script>
|
|
6
|
+
{% endblock %}
|
|
7
|
+
|
|
8
|
+
{% block content %}
|
|
9
|
+
|
|
10
|
+
<div id="edit-user"
|
|
11
|
+
data-root="{{ root }}"
|
|
12
|
+
data-role_sudo="{{ t('users.role.sudo') }}"
|
|
13
|
+
data-role_admin="{{ t('users.role.admin') }}"
|
|
14
|
+
data-role_editor="{{ t('users.role.editor') }}"
|
|
15
|
+
data-role_reader="{{ t('users.role.reader') }}"
|
|
16
|
+
>
|
|
17
|
+
<h2 style="display:flex; justify-content:space-between; align-items:center;">
|
|
18
|
+
{% if id == 0 %}
|
|
19
|
+
<span>{{ t('users.edit.title') }}: {{ t('users.edit.new') }}</span>
|
|
20
|
+
{% else %}
|
|
21
|
+
<span>{{ t('users.edit.title') }} #{{id}}: {{ t('users.edit.update') }}</span>
|
|
22
|
+
{% endif %}
|
|
23
|
+
</h2>
|
|
24
|
+
|
|
25
|
+
<form class="container mt-4" style="width:80%; margin-left:10%;">
|
|
26
|
+
<div class="row g-3">
|
|
27
|
+
|
|
28
|
+
<!-- Name -->
|
|
29
|
+
<div class="col-md-6">
|
|
30
|
+
<label for="name" class="form-label">{{ t('users.manage.name') }}</label>
|
|
31
|
+
<input type="text" class="form-control" id="name" placeholder="">
|
|
32
|
+
<div id="nameHelp" class="form-text"></div>
|
|
33
|
+
</div>
|
|
34
|
+
|
|
35
|
+
<!-- Surname -->
|
|
36
|
+
<div class="col-md-6">
|
|
37
|
+
<label for="surname" class="form-label">{{ t('users.manage.surname') }}</label>
|
|
38
|
+
<input type="text" class="form-control" id="surname" placeholder="">
|
|
39
|
+
<div id="surnameHelp" class="form-text"></div>
|
|
40
|
+
</div>
|
|
41
|
+
|
|
42
|
+
<!-- Username -->
|
|
43
|
+
<div class="col-md-6">
|
|
44
|
+
<label for="username" class="form-label">{{ t('users.manage.username') }}</label>
|
|
45
|
+
<input type="text" class="form-control" id="username" placeholder="">
|
|
46
|
+
<div id="usernameHelp" class="form-text"></div>
|
|
47
|
+
</div>
|
|
48
|
+
|
|
49
|
+
<!-- Email -->
|
|
50
|
+
<div class="col-md-6">
|
|
51
|
+
<label for="email" class="form-label">{{ t('users.manage.email') }}</label>
|
|
52
|
+
<input type="email" class="form-control" id="email" placeholder="">
|
|
53
|
+
<div id="emailHelp" class="form-text text-danger">
|
|
54
|
+
We'll never share your email with anyone else.
|
|
55
|
+
</div>
|
|
56
|
+
</div>
|
|
57
|
+
|
|
58
|
+
<!-- Password -->
|
|
59
|
+
<div class="col-md-6">
|
|
60
|
+
<label for="password" class="form-label">{{ t('users.edit.password') }}</label>
|
|
61
|
+
<input type="password" class="form-control" id="password" placeholder="">
|
|
62
|
+
<div id="passwordHelp" class="form-text text-danger">
|
|
63
|
+
We'll never share your email with anyone else.
|
|
64
|
+
</div>
|
|
65
|
+
</div>
|
|
66
|
+
|
|
67
|
+
<!-- Confirm Password -->
|
|
68
|
+
<div class="col-md-6">
|
|
69
|
+
<label for="password2" class="form-label">{{ t('users.edit.confirm_password') }}</label>
|
|
70
|
+
<input type="password" class="form-control" id="password2" placeholder="">
|
|
71
|
+
<div id="password2Help" class="form-text text-danger">
|
|
72
|
+
We'll never share your email with anyone else.
|
|
73
|
+
</div>
|
|
74
|
+
</div>
|
|
75
|
+
|
|
76
|
+
<!-- Role -->
|
|
77
|
+
<div class="col-md-6">
|
|
78
|
+
<label for="role" class="form-label">Role</label>
|
|
79
|
+
<select id="role" class="form-select">
|
|
80
|
+
<option value="0">{{ t('users.role.sudo') }}</option>
|
|
81
|
+
<option value="1">{{ t('users.role.admin') }}</option>
|
|
82
|
+
<option value="2">{{ t('users.role.editor') }}</option>
|
|
83
|
+
<option value="3">{{ t('users.role.reader') }}</option>
|
|
84
|
+
</select>
|
|
85
|
+
</div>
|
|
86
|
+
|
|
87
|
+
<!-- Buttons -->
|
|
88
|
+
<div class="col-12 text-center mt-4">
|
|
89
|
+
<button @click="save()" type="submit" class="btn btn-primary me-2">{{ t('users.edit.save') }}</button>
|
|
90
|
+
<button @click="cancel()" type="button" class="btn btn-secondary">{{ t('users.edit.cancel') }}</button>
|
|
91
|
+
</div>
|
|
92
|
+
|
|
93
|
+
</div>
|
|
94
|
+
</form>
|
|
95
|
+
|
|
96
|
+
</div>
|
|
97
|
+
|
|
98
|
+
{% endblock %}
|
|
@@ -8,45 +8,51 @@
|
|
|
8
8
|
|
|
9
9
|
{% block content %}
|
|
10
10
|
|
|
11
|
-
<
|
|
12
|
-
<span>{{ t('users.manage.title') }}</span>
|
|
13
|
-
<i style="color:gray; cursor:pointer; font-size:24px;"
|
|
14
|
-
class="fa-solid fa-user-plus" title="{{ t('users.manage.new') }}"></i>
|
|
15
|
-
</h2>
|
|
16
|
-
<table id="manage-users" class="table"
|
|
11
|
+
<div id="manage-users"
|
|
17
12
|
data-root="{{ root }}"
|
|
18
13
|
data-role_sudo="{{ t('users.role.sudo') }}"
|
|
19
14
|
data-role_admin="{{ t('users.role.admin') }}"
|
|
20
15
|
data-role_editor="{{ t('users.role.editor') }}"
|
|
21
16
|
data-role_reader="{{ t('users.role.reader') }}"
|
|
17
|
+
data-cur_id="{{ cur_id }}"
|
|
22
18
|
>
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
<
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
<
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
19
|
+
<h2 style="display:flex; justify-content:space-between; align-items:center;">
|
|
20
|
+
<span>{{ t('users.manage.title') }}</span>
|
|
21
|
+
<i @click="newUser()" style="color:gray; cursor:pointer; font-size:24px;"
|
|
22
|
+
class="fa-solid fa-user-plus" title="{{ t('users.manage.new') }}"></i>
|
|
23
|
+
</h2>
|
|
24
|
+
<table class="table">
|
|
25
|
+
<thead>
|
|
26
|
+
<tr>
|
|
27
|
+
<td>#</td>
|
|
28
|
+
<td>{{ t('users.manage.name') }}</td>
|
|
29
|
+
<td>{{ t('users.manage.surname') }}</td>
|
|
30
|
+
<td>{{ t('users.manage.username') }}</td>
|
|
31
|
+
<td>{{ t('users.manage.email') }}</td>
|
|
32
|
+
<td>{{ t('users.manage.role') }}</td>
|
|
33
|
+
<td></td>
|
|
34
|
+
<td></td>
|
|
35
|
+
</tr>
|
|
36
|
+
</thead>
|
|
37
|
+
<tbody>
|
|
38
|
+
<tr v-for="user in users">
|
|
39
|
+
<td v-text="user.id"></td>
|
|
40
|
+
<td v-text="user.name"></td>
|
|
41
|
+
<td v-text="user.surname"></td>
|
|
42
|
+
<td v-text="user.username"></td>
|
|
43
|
+
<td v-text="user.email"></td>
|
|
44
|
+
<td v-text="roleByCode(user.role)"></td>
|
|
45
|
+
<td @click="editUser(user.id)"><i style="cursor:pointer; color:blue"
|
|
46
|
+
class="fa-solid fa-pen-to-square" title="{{ t('users.manage.edit') }}"></i>
|
|
47
|
+
</td>
|
|
48
|
+
<td v-if="cur_id != user.id" @click="deleteUser(user.id)">
|
|
49
|
+
<i style="cursor:pointer; color:red"
|
|
50
|
+
class="fa-solid fa-trash-can" title="{{ t('users.manage.delete') }}">
|
|
51
|
+
</i>
|
|
52
|
+
</td>
|
|
53
|
+
<td v-else></td>
|
|
54
|
+
</tr>
|
|
55
|
+
</tbody>
|
|
56
|
+
</table>
|
|
57
|
+
</div>
|
|
52
58
|
{% endblock %}
|