Add an user management page for admins
This commit is contained in:
@@ -100,6 +100,14 @@ onMounted(() => {
|
||||
<RouterLink v-if="authStore.user" to="/add" class="navbar-item" activeClass="is-active">
|
||||
{{ $t('navbar.addbook') }}
|
||||
</RouterLink>
|
||||
<RouterLink
|
||||
v-if="authStore.user && authStore.user.admin"
|
||||
to="/admin/users"
|
||||
class="navbar-item"
|
||||
activeClass="is-active"
|
||||
>
|
||||
{{ $t('navbar.usersmgt') }}
|
||||
</RouterLink>
|
||||
<div
|
||||
v-if="authStore.user && appInfo && !appInfo.demoMode"
|
||||
class="navbar-item is-hidden-desktop"
|
||||
|
||||
@@ -23,7 +23,7 @@ const passwordError = computed(() => {
|
||||
return extractFormErrorFromField('Password', errors.value)
|
||||
})
|
||||
|
||||
async function onSubmit(e) {
|
||||
async function onSubmit() {
|
||||
const res = await postLogin(user)
|
||||
if (res.ok) {
|
||||
let json = await res.json()
|
||||
@@ -36,7 +36,7 @@ async function onSubmit(e) {
|
||||
}
|
||||
|
||||
async function login(username, json) {
|
||||
useAuthStore().login({ username: username, token: json['token'] })
|
||||
useAuthStore().login({ username: username, admin: json['admin'], token: json['token'] })
|
||||
}
|
||||
</script>
|
||||
|
||||
|
||||
76
front/src/UsersManagement.vue
Normal file
76
front/src/UsersManagement.vue
Normal file
@@ -0,0 +1,76 @@
|
||||
<script setup>
|
||||
import { ref, computed } from 'vue'
|
||||
import { getUsers } from './api.js'
|
||||
|
||||
const limit = 50
|
||||
const pageNumber = ref(1)
|
||||
|
||||
const offset = computed(() => (pageNumber.value - 1) * limit)
|
||||
|
||||
const data = ref(null)
|
||||
const error = ref(null)
|
||||
|
||||
let totalUsersNumber = computed(() =>
|
||||
typeof data != 'undefined' && data.value != null ? data.value['count'] : 0,
|
||||
)
|
||||
let pageTotal = computed(() => Math.ceil(totalUsersNumber.value / limit))
|
||||
|
||||
fetchData()
|
||||
|
||||
function fetchData() {
|
||||
getUsers(data, error, limit, offset.value)
|
||||
}
|
||||
|
||||
function pageChange(newPageNumber) {
|
||||
pageNumber.value = newPageNumber
|
||||
data.value = null
|
||||
fetchData()
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<div v-if="error">{{ $t('usersmanagement.error', { error: error.message }) }}</div>
|
||||
<div v-else-if="data">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<th>#</th>
|
||||
<th>{{ $t('usersmanagement.name') }}</th>
|
||||
<th>{{ $t('usersmanagement.admin') }}</th>
|
||||
<th>
|
||||
<abbr :title="$t('usersmanagement.addedbookshelp')">{{
|
||||
$t('usersmanagement.addedbooks')
|
||||
}}</abbr>
|
||||
</th>
|
||||
<th>
|
||||
<abbr :title="$t('usersmanagement.bookshelp')">{{ $t('usersmanagement.books') }}</abbr>
|
||||
</th>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr v-for="user in data.users" :key="user.id">
|
||||
<th class="numbercell">{{ user.id }}</th>
|
||||
<td>{{ user.name }}</td>
|
||||
<td class="boolcell"><input type="checkbox" disabled :checked="user.admin" /></td>
|
||||
<td class="numbercell">{{ user.addedbookscount }}</td>
|
||||
<td class="numbercell">{{ user.userbookscount }}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
<Pagination
|
||||
:pageNumber="pageNumber"
|
||||
:pageTotal="pageTotal"
|
||||
maxItemDisplayed="11"
|
||||
@pageChange="pageChange"
|
||||
/>
|
||||
</div>
|
||||
<div v-else>{{ $t('usersmanagement.loading') }}</div>
|
||||
</template>
|
||||
|
||||
<style scoped>
|
||||
.boolcell {
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
.numbercell {
|
||||
text-align: right;
|
||||
}
|
||||
</style>
|
||||
@@ -118,6 +118,11 @@ export function getBookCall(id) {
|
||||
return userFetch('/ws/book/' + id)
|
||||
}
|
||||
|
||||
export function getUsers(data, error, limit, offset) {
|
||||
const queryParams = new URLSearchParams({ limit: limit, offset: offset })
|
||||
return useFetch(data, error, '/ws/admin/users' + '?' + queryParams.toString())
|
||||
}
|
||||
|
||||
export function postBook(book) {
|
||||
return genericPayloadCall('/ws/book', book.value, 'POST')
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"logout": "Log out",
|
||||
"signup": "Sign up",
|
||||
"search": "Search",
|
||||
"usersmgt": "Users Management",
|
||||
"login": "Log In"
|
||||
},
|
||||
"barcode": {
|
||||
@@ -100,5 +101,15 @@
|
||||
},
|
||||
"collection": {
|
||||
"error": "Error when loading collection: {error}"
|
||||
},
|
||||
"usersmanagement": {
|
||||
"error": "Error when loading users: {error}",
|
||||
"name": "Name",
|
||||
"admin": "Is Admin ?",
|
||||
"addedbooks": "Added Books",
|
||||
"addedbookshelp": "Number of books the user created or imported.",
|
||||
"books": "Books Number",
|
||||
"bookshelp": "Total number of books of the user.",
|
||||
"loading": "Loading..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
"logout": "Se déconnecter",
|
||||
"signup": "S'inscrire",
|
||||
"search": "Rechercher",
|
||||
"usersmgt": "Gestion Des Utilisateurs",
|
||||
"login": "Se connecter"
|
||||
},
|
||||
"barcode": {
|
||||
@@ -100,5 +101,15 @@
|
||||
},
|
||||
"collection": {
|
||||
"error": "Erreur pendant le chargement de la liste : {error}"
|
||||
},
|
||||
"usersmanagement": {
|
||||
"error": "Erreur pendant le chargement des utilisateurs: {error}",
|
||||
"name": "Nom",
|
||||
"admin": "Administrateur ?",
|
||||
"addedbooks": "Livres Ajoutés",
|
||||
"addedbookshelp": "Nombre de livres créés ou importés par l'utilisateur.",
|
||||
"books": "Nombre De Livres",
|
||||
"bookshelp": "Le nombre total de livres de cet utilisateur.",
|
||||
"loading": "Chargement..."
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import ScanBook from './ScanBook.vue'
|
||||
import SearchBook from './SearchBook.vue'
|
||||
import ImportInventaire from './ImportInventaire.vue'
|
||||
import InstanceBrowser from './InstanceBrowser.vue'
|
||||
import UsersManagement from './UsersManagement.vue'
|
||||
import { useAuthStore } from './auth.store'
|
||||
|
||||
const routes = [
|
||||
@@ -30,6 +31,7 @@ const routes = [
|
||||
{ path: '/add', component: BookFormEdit },
|
||||
{ path: '/signup', component: SignUp },
|
||||
{ path: '/login', component: LogIn },
|
||||
{ path: '/admin/users', component: UsersManagement },
|
||||
]
|
||||
|
||||
export const router = createRouter({
|
||||
|
||||
Reference in New Issue
Block a user