0
1
Fork 0

Create access log view

This commit is contained in:
William Buezas 2024-09-16 13:24:43 -03:00
parent 85eee7bb7a
commit cc44041e31
11 changed files with 139 additions and 7 deletions

View File

@ -1,7 +1,7 @@
<script setup>
const props = defineProps({
clickable: { type: Boolean, default: true },
rounded: { type: Boolean, default: true }
rounded: { type: Boolean, default: false }
});
const emit = defineEmits(['click']);
@ -18,8 +18,11 @@ const handleClick = () => {
v-bind="$attrs"
v-ripple="clickable"
:clickable="clickable"
class="full-width row items-center justify-between card no-border-radius bg-white"
:class="{ 'cursor-pointer': clickable, 'no-radius': !rounded }"
class="full-width row items-center justify-between card bg-white"
:class="[
rounded ? 'default-radius' : 'no-radius',
{ 'cursor-pointer': clickable }
]"
@click="handleClick()"
>
<div

View File

@ -69,6 +69,7 @@ export default {
Checkout: `Configurar l'encarrec`,
'Address details': 'Configuració',
'Admin news details': `Afegir o editar notícia`,
'Access log': 'Registre daccés',
//
orderLoadedIntoBasket: 'Comanda carregada a la cistella!',
loadAnOrder:

View File

@ -81,6 +81,7 @@ export default {
Checkout: 'Configure order',
'Address details': 'Configuration',
'Admin news details': 'Add or edit new',
'Access log': 'Access log',
//
orderLoadedIntoBasket: 'Order loaded into basket!',
loadAnOrder: 'Please load a pending order to the cart or start a new one',

View File

@ -87,6 +87,7 @@ export default {
Checkout: 'Configurar pedido',
'Address details': 'Configuración',
'Admin news details': 'Añadir o editar noticia',
'Access log': 'Registro de accesos',
//
orderLoadedIntoBasket: '¡Pedido cargado en la cesta!',
loadAnOrder:

View File

@ -69,6 +69,7 @@ export default {
Checkout: 'Configurer la commande',
'Address details': 'Configuration',
'Admin news details': 'Ajouter ou éditer une nouvelle',
'Access log': "Journal d'accès",
//
orderLoadedIntoBasket: 'Commande chargée dans le panier!',
loadAnOrder:

View File

@ -68,6 +68,7 @@ export default {
Checkout: 'Configurar encomenda',
'Address details': 'Configuração',
'Admin news details': 'Adicionar ou editar notícia',
'Access log': 'Registo de acessos',
//
orderLoadedIntoBasket: 'Pedido carregado na cesta!',
loadAnOrder: 'Carregue um pedido pendente no carrinho ou inicie um novo',

View File

@ -31,7 +31,13 @@ export const formatDate = (timeStamp, format = 'YYYY-MM-DD') => {
*/
export const formatDateTitle = (
timeStamp,
options = { showTime: false, showSeconds: false, shortDay: false }
options = {
showTime: false,
showSeconds: false,
shortDay: false,
shortMonth: false,
includeOfString: true
}
) => {
if (!timeStamp) return '';
const { t } = i18n.global;
@ -42,8 +48,10 @@ export const formatDateTitle = (
: ` [${t('at')}] HH:mm`
: '';
const day = options.shortDay ? 'dd' : 'dddd';
const month = options.shortMonth ? 'MMM' : 'MMMM';
const ofString = options.includeOfString ? ` [${t('of')}] ` : '';
const formatString = `${day}, D [${t('of')}] MMMM [${t('of')}] YYYY${timeFormat}`;
const formatString = `${day}, D${ofString} ${month}${ofString} YYYY${timeFormat}`;
const formattedString = formatDate(timeStamp, formatString);
return formattedString;

View File

@ -0,0 +1,106 @@
<script setup>
import { onMounted, inject, ref } from 'vue';
import { useRoute } from 'vue-router';
import CardList from 'src/components/ui/CardList.vue';
import { formatDateTitle } from 'src/lib/filters.js';
const jApi = inject('jApi');
const route = useRoute();
const accessLogs = ref([]);
const user = ref(null);
const getUser = async () => {
try {
if (!route.params.id) return;
const [data] = await jApi.query(
`SELECT u.id, u.name user, u.nickname, u.email, c.phone, r.name role
FROM account.user u
JOIN account.role r ON r.id = u.role
LEFT JOIN vn.client c ON c.id = u.id
WHERE u.id = #user`,
{ user: route.params.id }
);
user.value = data;
} catch (error) {
console.error('Error getting user:', error);
}
};
const getAccessLogs = async () => {
try {
accessLogs.value = await jApi.query(
`SELECT u.stamp, a.platform, a.browser, a.version, a.javascript, a.cookies
FROM visitUser u
JOIN visitAccess c ON c.id = u.accessFk
JOIN visitAgent a ON a.id = c.agentFk
WHERE u.userFk = #user
ORDER BY u.stamp DESC
LIMIT 8`,
{ user: route.params.id }
);
} catch (error) {
console.error('Error getting access logs:', error);
}
};
onMounted(async () => {
getUser();
getAccessLogs();
});
</script>
<template>
<QPage class="vn-w-xs">
<CardList
v-if="user"
:key="index"
:clickable="false"
rounded
class="q-mb-md"
>
<template #content>
<span class="text-bold text-h5 q-mb-sm">
{{ user?.nickname }}
</span>
<span>#{{ user?.id }} - {{ user.user }} </span>
<span>{{ user?.role }} </span>
<span>{{ user?.email }} </span>
<span>{{ user?.phone }} </span>
</template>
</CardList>
<QList>
<CardList
v-for="(accessLog, index) in accessLogs"
:key="index"
:clickable="false"
>
<template #content>
<span>
{{
formatDateTitle(accessLog.stamp, {
showTime: true,
shortDay: true,
shortMonth: true,
showSeconds: true
})
}}
</span>
<span
v-if="
accessLog.platform &&
accessLog.browser &&
accessLog.version
"
>
{{ accessLog.platform }} - {{ accessLog.browser }} -
{{ accessLog.version }}
</span>
</template>
</CardList>
</QList>
</QPage>
</template>

View File

@ -91,6 +91,7 @@ onBeforeUnmount(() => clearInterval(intervalId.value));
v-else
v-for="(connection, index) in connections"
:key="index"
:to="{ name: 'accessLog', params: { id: connection.userId } }"
>
<template #content>
<span class="text-bold q-mb-sm">
@ -132,6 +133,7 @@ onBeforeUnmount(() => clearInterval(intervalId.value));
</QBtn>
</template>
</CardList>
<pre>{{ connections }}</pre>
</QList>
</QPage>
</template>

View File

@ -64,7 +64,7 @@ const supplantUser = async user => {
v-else
v-for="(user, index) in users"
:key="index"
:clickable="false"
:to="{ name: 'accessLog', params: { id: user.id } }"
>
<template #content>
<span class="text-bold q-mb-sm">

View File

@ -143,12 +143,20 @@ const routes = [
},
{
name: 'adminUsers',
path: 'admin/users',
path: 'admin/users:/:id?',
meta: {
title: 'Users'
},
component: () => import('pages/Admin/UsersView.vue')
},
{
name: 'accessLog',
path: 'admin/access-log/:id?',
meta: {
title: 'Access log'
},
component: () => import('pages/Admin/AccessLogView.vue')
},
{
name: 'adminConnections',
path: 'admin/connections',