Create access log view
This commit is contained in:
parent
85eee7bb7a
commit
cc44041e31
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
clickable: { type: Boolean, default: true },
|
clickable: { type: Boolean, default: true },
|
||||||
rounded: { type: Boolean, default: true }
|
rounded: { type: Boolean, default: false }
|
||||||
});
|
});
|
||||||
|
|
||||||
const emit = defineEmits(['click']);
|
const emit = defineEmits(['click']);
|
||||||
|
@ -18,8 +18,11 @@ const handleClick = () => {
|
||||||
v-bind="$attrs"
|
v-bind="$attrs"
|
||||||
v-ripple="clickable"
|
v-ripple="clickable"
|
||||||
:clickable="clickable"
|
:clickable="clickable"
|
||||||
class="full-width row items-center justify-between card no-border-radius bg-white"
|
class="full-width row items-center justify-between card bg-white"
|
||||||
:class="{ 'cursor-pointer': clickable, 'no-radius': !rounded }"
|
:class="[
|
||||||
|
rounded ? 'default-radius' : 'no-radius',
|
||||||
|
{ 'cursor-pointer': clickable }
|
||||||
|
]"
|
||||||
@click="handleClick()"
|
@click="handleClick()"
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
|
|
@ -69,6 +69,7 @@ export default {
|
||||||
Checkout: `Configurar l'encarrec`,
|
Checkout: `Configurar l'encarrec`,
|
||||||
'Address details': 'Configuració',
|
'Address details': 'Configuració',
|
||||||
'Admin news details': `Afegir o editar notícia`,
|
'Admin news details': `Afegir o editar notícia`,
|
||||||
|
'Access log': 'Registre d’accés',
|
||||||
//
|
//
|
||||||
orderLoadedIntoBasket: 'Comanda carregada a la cistella!',
|
orderLoadedIntoBasket: 'Comanda carregada a la cistella!',
|
||||||
loadAnOrder:
|
loadAnOrder:
|
||||||
|
|
|
@ -81,6 +81,7 @@ export default {
|
||||||
Checkout: 'Configure order',
|
Checkout: 'Configure order',
|
||||||
'Address details': 'Configuration',
|
'Address details': 'Configuration',
|
||||||
'Admin news details': 'Add or edit new',
|
'Admin news details': 'Add or edit new',
|
||||||
|
'Access log': 'Access log',
|
||||||
//
|
//
|
||||||
orderLoadedIntoBasket: 'Order loaded into basket!',
|
orderLoadedIntoBasket: 'Order loaded into basket!',
|
||||||
loadAnOrder: 'Please load a pending order to the cart or start a new one',
|
loadAnOrder: 'Please load a pending order to the cart or start a new one',
|
||||||
|
|
|
@ -87,6 +87,7 @@ export default {
|
||||||
Checkout: 'Configurar pedido',
|
Checkout: 'Configurar pedido',
|
||||||
'Address details': 'Configuración',
|
'Address details': 'Configuración',
|
||||||
'Admin news details': 'Añadir o editar noticia',
|
'Admin news details': 'Añadir o editar noticia',
|
||||||
|
'Access log': 'Registro de accesos',
|
||||||
//
|
//
|
||||||
orderLoadedIntoBasket: '¡Pedido cargado en la cesta!',
|
orderLoadedIntoBasket: '¡Pedido cargado en la cesta!',
|
||||||
loadAnOrder:
|
loadAnOrder:
|
||||||
|
|
|
@ -69,6 +69,7 @@ export default {
|
||||||
Checkout: 'Configurer la commande',
|
Checkout: 'Configurer la commande',
|
||||||
'Address details': 'Configuration',
|
'Address details': 'Configuration',
|
||||||
'Admin news details': 'Ajouter ou éditer une nouvelle',
|
'Admin news details': 'Ajouter ou éditer une nouvelle',
|
||||||
|
'Access log': "Journal d'accès",
|
||||||
//
|
//
|
||||||
orderLoadedIntoBasket: 'Commande chargée dans le panier!',
|
orderLoadedIntoBasket: 'Commande chargée dans le panier!',
|
||||||
loadAnOrder:
|
loadAnOrder:
|
||||||
|
|
|
@ -68,6 +68,7 @@ export default {
|
||||||
Checkout: 'Configurar encomenda',
|
Checkout: 'Configurar encomenda',
|
||||||
'Address details': 'Configuração',
|
'Address details': 'Configuração',
|
||||||
'Admin news details': 'Adicionar ou editar notícia',
|
'Admin news details': 'Adicionar ou editar notícia',
|
||||||
|
'Access log': 'Registo de acessos',
|
||||||
//
|
//
|
||||||
orderLoadedIntoBasket: 'Pedido carregado na cesta!',
|
orderLoadedIntoBasket: 'Pedido carregado na cesta!',
|
||||||
loadAnOrder: 'Carregue um pedido pendente no carrinho ou inicie um novo',
|
loadAnOrder: 'Carregue um pedido pendente no carrinho ou inicie um novo',
|
||||||
|
|
|
@ -31,7 +31,13 @@ export const formatDate = (timeStamp, format = 'YYYY-MM-DD') => {
|
||||||
*/
|
*/
|
||||||
export const formatDateTitle = (
|
export const formatDateTitle = (
|
||||||
timeStamp,
|
timeStamp,
|
||||||
options = { showTime: false, showSeconds: false, shortDay: false }
|
options = {
|
||||||
|
showTime: false,
|
||||||
|
showSeconds: false,
|
||||||
|
shortDay: false,
|
||||||
|
shortMonth: false,
|
||||||
|
includeOfString: true
|
||||||
|
}
|
||||||
) => {
|
) => {
|
||||||
if (!timeStamp) return '';
|
if (!timeStamp) return '';
|
||||||
const { t } = i18n.global;
|
const { t } = i18n.global;
|
||||||
|
@ -42,8 +48,10 @@ export const formatDateTitle = (
|
||||||
: ` [${t('at')}] HH:mm`
|
: ` [${t('at')}] HH:mm`
|
||||||
: '';
|
: '';
|
||||||
const day = options.shortDay ? 'dd' : 'dddd';
|
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);
|
const formattedString = formatDate(timeStamp, formatString);
|
||||||
return formattedString;
|
return formattedString;
|
||||||
|
|
|
@ -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>
|
|
@ -91,6 +91,7 @@ onBeforeUnmount(() => clearInterval(intervalId.value));
|
||||||
v-else
|
v-else
|
||||||
v-for="(connection, index) in connections"
|
v-for="(connection, index) in connections"
|
||||||
:key="index"
|
:key="index"
|
||||||
|
:to="{ name: 'accessLog', params: { id: connection.userId } }"
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<span class="text-bold q-mb-sm">
|
<span class="text-bold q-mb-sm">
|
||||||
|
@ -132,6 +133,7 @@ onBeforeUnmount(() => clearInterval(intervalId.value));
|
||||||
</QBtn>
|
</QBtn>
|
||||||
</template>
|
</template>
|
||||||
</CardList>
|
</CardList>
|
||||||
|
<pre>{{ connections }}</pre>
|
||||||
</QList>
|
</QList>
|
||||||
</QPage>
|
</QPage>
|
||||||
</template>
|
</template>
|
||||||
|
|
|
@ -64,7 +64,7 @@ const supplantUser = async user => {
|
||||||
v-else
|
v-else
|
||||||
v-for="(user, index) in users"
|
v-for="(user, index) in users"
|
||||||
:key="index"
|
:key="index"
|
||||||
:clickable="false"
|
:to="{ name: 'accessLog', params: { id: user.id } }"
|
||||||
>
|
>
|
||||||
<template #content>
|
<template #content>
|
||||||
<span class="text-bold q-mb-sm">
|
<span class="text-bold q-mb-sm">
|
||||||
|
|
|
@ -143,12 +143,20 @@ const routes = [
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
name: 'adminUsers',
|
name: 'adminUsers',
|
||||||
path: 'admin/users',
|
path: 'admin/users:/:id?',
|
||||||
meta: {
|
meta: {
|
||||||
title: 'Users'
|
title: 'Users'
|
||||||
},
|
},
|
||||||
component: () => import('pages/Admin/UsersView.vue')
|
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',
|
name: 'adminConnections',
|
||||||
path: 'admin/connections',
|
path: 'admin/connections',
|
||||||
|
|
Loading…
Reference in New Issue