Merge pull request 'fixes #5357 Convertir sección de histórico en componente reutilizable vnLog' (!48) from 5357-vnLog-component into dev
gitea/salix-front/pipeline/head This commit looks good
Details
gitea/salix-front/pipeline/head This commit looks good
Details
Reviewed-on: #48 Reviewed-by: Juan Ferrer <juan@verdnatura.es>
This commit is contained in:
commit
06645d941b
|
@ -39,6 +39,7 @@ onMounted(async () => {
|
||||||
});
|
});
|
||||||
|
|
||||||
async function fetch() {
|
async function fetch() {
|
||||||
|
try {
|
||||||
const filter = Object.assign({}, $props.filter);
|
const filter = Object.assign({}, $props.filter);
|
||||||
if ($props.where) filter.where = $props.where;
|
if ($props.where) filter.where = $props.where;
|
||||||
if ($props.sortBy) filter.order = $props.sortBy;
|
if ($props.sortBy) filter.order = $props.sortBy;
|
||||||
|
@ -49,6 +50,9 @@ async function fetch() {
|
||||||
});
|
});
|
||||||
|
|
||||||
emit('onFetch', data);
|
emit('onFetch', data);
|
||||||
|
} catch (e) {
|
||||||
|
//
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const render = () => {
|
const render = () => {
|
||||||
|
|
|
@ -0,0 +1,208 @@
|
||||||
|
<script setup>
|
||||||
|
import { useI18n } from 'vue-i18n';
|
||||||
|
import { useRoute } from 'vue-router';
|
||||||
|
import { useSession } from 'src/composables/useSession';
|
||||||
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
||||||
|
import VnLogFilter from 'src/components/common/VnLogFilter.vue';
|
||||||
|
|
||||||
|
import { toDate } from 'src/filters';
|
||||||
|
|
||||||
|
const stateStore = useStateStore();
|
||||||
|
const route = useRoute();
|
||||||
|
const session = useSession();
|
||||||
|
const token = session.getToken();
|
||||||
|
const { t } = useI18n();
|
||||||
|
|
||||||
|
const props = defineProps({
|
||||||
|
model: {
|
||||||
|
type: String,
|
||||||
|
default: null,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
name: 'property',
|
||||||
|
label: 'Property',
|
||||||
|
field: (row) => t(`properties.${row.property}`),
|
||||||
|
align: 'left',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'before',
|
||||||
|
label: 'Before',
|
||||||
|
field: (row) => formatValue(row.before),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: 'after',
|
||||||
|
label: 'After',
|
||||||
|
field: (row) => formatValue(row.after),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
function formatValue(value) {
|
||||||
|
if (typeof value === 'boolean') {
|
||||||
|
return value ? t('Yes') : t('No');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isNaN(value) && !isNaN(Date.parse(value))) {
|
||||||
|
return toDate(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value === undefined) {
|
||||||
|
return t('Nothing');
|
||||||
|
}
|
||||||
|
|
||||||
|
return `"${value}"`;
|
||||||
|
}
|
||||||
|
|
||||||
|
function actionColor(action) {
|
||||||
|
if (action === 'insert') return 'positive';
|
||||||
|
if (action === 'update') return 'positive';
|
||||||
|
if (action === 'delete') return 'negative';
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
<template>
|
||||||
|
<div class="column items-center">
|
||||||
|
<QTimeline class="q-pa-md">
|
||||||
|
<QTimelineEntry heading tag="h4"> {{ t('Audit logs') }} </QTimelineEntry>
|
||||||
|
<VnPaginate
|
||||||
|
:data-key="`${props.model}Logs`"
|
||||||
|
:url="`${props.model}s/${route.params.id}/logs`"
|
||||||
|
order="id DESC"
|
||||||
|
:offset="100"
|
||||||
|
:limit="5"
|
||||||
|
auto-load
|
||||||
|
>
|
||||||
|
<template #body="{ rows }">
|
||||||
|
<template v-for="log of rows" :key="log.id">
|
||||||
|
<QTimelineEntry
|
||||||
|
:avatar="`/api/Images/user/160x160/${log.userFk}/download?access_token=${token}`"
|
||||||
|
>
|
||||||
|
<template #subtitle>
|
||||||
|
{{ log.userName }} -
|
||||||
|
{{
|
||||||
|
toDate(log.created, {
|
||||||
|
dateStyle: 'medium',
|
||||||
|
timeStyle: 'short',
|
||||||
|
})
|
||||||
|
}}
|
||||||
|
</template>
|
||||||
|
<template #title>
|
||||||
|
<QChip :color="actionColor(log.action)">
|
||||||
|
{{ t(`actions.${log.action}`) }}
|
||||||
|
</QChip>
|
||||||
|
{{ t(`models.${log.model}`) }}
|
||||||
|
</template>
|
||||||
|
<QTable
|
||||||
|
:rows="log.changes"
|
||||||
|
:columns="columns"
|
||||||
|
row-key="property"
|
||||||
|
hide-pagination
|
||||||
|
dense
|
||||||
|
flat
|
||||||
|
>
|
||||||
|
<template #header="propsLabel">
|
||||||
|
<QTr :props="propsLabel">
|
||||||
|
<QTh
|
||||||
|
v-for="col in propsLabel.cols"
|
||||||
|
:key="col.name"
|
||||||
|
:props="propsLabel"
|
||||||
|
>
|
||||||
|
{{ t(col.label) }}
|
||||||
|
</QTh>
|
||||||
|
</QTr>
|
||||||
|
</template>
|
||||||
|
</QTable>
|
||||||
|
</QTimelineEntry>
|
||||||
|
</template>
|
||||||
|
</template>
|
||||||
|
</VnPaginate>
|
||||||
|
</QTimeline>
|
||||||
|
</div>
|
||||||
|
<Teleport v-if="stateStore.isHeaderMounted()" to="#actions-append">
|
||||||
|
<div class="row q-gutter-x-sm">
|
||||||
|
<QBtn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu">
|
||||||
|
<QTooltip bottom anchor="bottom right">
|
||||||
|
{{ t('globals.collapseMenu') }}
|
||||||
|
</QTooltip>
|
||||||
|
</QBtn>
|
||||||
|
</div>
|
||||||
|
</Teleport>
|
||||||
|
<QDrawer v-model="stateStore.rightDrawer" show-if-above side="right" :width="300">
|
||||||
|
<QScrollArea class="fit text-grey-8">
|
||||||
|
<VnLogFilter :data-key="`${props.model}Logs`" />
|
||||||
|
</QScrollArea>
|
||||||
|
</QDrawer>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<style lang="scss" scoped>
|
||||||
|
.q-timeline {
|
||||||
|
width: 100%;
|
||||||
|
max-width: 80em;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
<i18n>
|
||||||
|
en:
|
||||||
|
actions:
|
||||||
|
insert: Creates
|
||||||
|
update: Updates
|
||||||
|
delete: Deletes
|
||||||
|
models:
|
||||||
|
Claim: Claim
|
||||||
|
ClaimDms: Document
|
||||||
|
ClaimBeginning: Claimed Sales
|
||||||
|
ClaimObservation: Observation
|
||||||
|
properties:
|
||||||
|
id: ID
|
||||||
|
claimFk: Claim ID
|
||||||
|
saleFk: Sale ID
|
||||||
|
quantity: Quantity
|
||||||
|
observation: Observation
|
||||||
|
ticketCreated: Created
|
||||||
|
created: Created
|
||||||
|
isChargedToMana: Charged to mana
|
||||||
|
hasToPickUp: Has to pick Up
|
||||||
|
dmsFk: Document ID
|
||||||
|
text: Description
|
||||||
|
claimStateFk: Claim State
|
||||||
|
workerFk: Worker
|
||||||
|
clientFk: Customer
|
||||||
|
rma: RMA
|
||||||
|
responsibility: Responsibility
|
||||||
|
packages: Packages
|
||||||
|
es:
|
||||||
|
Audit logs: Registros de auditoría
|
||||||
|
Property: Propiedad
|
||||||
|
Before: Antes
|
||||||
|
After: Después
|
||||||
|
Yes: Si
|
||||||
|
Nothing: Nada
|
||||||
|
actions:
|
||||||
|
insert: Crea
|
||||||
|
update: Actualiza
|
||||||
|
delete: Elimina
|
||||||
|
models:
|
||||||
|
Claim: Reclamación
|
||||||
|
ClaimDms: Documento
|
||||||
|
ClaimBeginning: Línea reclamada
|
||||||
|
ClaimObservation: Observación
|
||||||
|
properties:
|
||||||
|
id: ID
|
||||||
|
claimFk: ID reclamación
|
||||||
|
saleFk: ID linea de venta
|
||||||
|
quantity: Cantidad
|
||||||
|
observation: Observación
|
||||||
|
ticketCreated: Creado
|
||||||
|
created: Creado
|
||||||
|
isChargedToMana: Cargado a maná
|
||||||
|
hasToPickUp: Se debe recoger
|
||||||
|
dmsFk: ID documento
|
||||||
|
text: Descripción
|
||||||
|
claimStateFk: Estado de la reclamación
|
||||||
|
workerFk: Trabajador
|
||||||
|
clientFk: Cliente
|
||||||
|
rma: RMA
|
||||||
|
responsibility: Responsabilidad
|
||||||
|
packages: Bultos
|
||||||
|
</i18n>
|
|
@ -1,201 +1,6 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { useI18n } from 'vue-i18n';
|
import VnLog from 'src/components/common/VnLog.vue';
|
||||||
import { useRoute } from 'vue-router';
|
|
||||||
import { useSession } from 'src/composables/useSession';
|
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
|
||||||
import VnPaginate from 'src/components/ui/VnPaginate.vue';
|
|
||||||
import ClaimLogFilter from './ClaimLogFilter.vue';
|
|
||||||
|
|
||||||
import { toDate } from 'src/filters';
|
|
||||||
|
|
||||||
const stateStore = useStateStore();
|
|
||||||
const route = useRoute();
|
|
||||||
const session = useSession();
|
|
||||||
const token = session.getToken();
|
|
||||||
const { t } = useI18n();
|
|
||||||
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
name: 'property',
|
|
||||||
label: 'Property',
|
|
||||||
field: (row) => t(`properties.${row.property}`),
|
|
||||||
align: 'left',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'before',
|
|
||||||
label: 'Before',
|
|
||||||
field: (row) => formatValue(row.before),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
name: 'after',
|
|
||||||
label: 'After',
|
|
||||||
field: (row) => formatValue(row.after),
|
|
||||||
},
|
|
||||||
];
|
|
||||||
|
|
||||||
function formatValue(value) {
|
|
||||||
if (typeof value === 'boolean') {
|
|
||||||
return value ? t('Yes') : t('No');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (isNaN(value) && !isNaN(Date.parse(value))) {
|
|
||||||
return toDate(value);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (value === undefined) {
|
|
||||||
return t('Nothing');
|
|
||||||
}
|
|
||||||
|
|
||||||
return `"${value}"`;
|
|
||||||
}
|
|
||||||
|
|
||||||
function actionColor(action) {
|
|
||||||
if (action === 'insert') return 'positive';
|
|
||||||
if (action === 'update') return 'positive';
|
|
||||||
if (action === 'delete') return 'negative';
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<div class="column items-center">
|
<VnLog model="Claim"></VnLog>
|
||||||
<QTimeline class="q-pa-md">
|
|
||||||
<QTimelineEntry heading tag="h4"> {{ t('Audit logs') }} </QTimelineEntry>
|
|
||||||
<VnPaginate
|
|
||||||
data-key="ClaimLogs"
|
|
||||||
:url="`Claims/${route.params.id}/logs`"
|
|
||||||
order="id DESC"
|
|
||||||
:offset="100"
|
|
||||||
:limit="5"
|
|
||||||
auto-load
|
|
||||||
>
|
|
||||||
<template #body="{ rows }">
|
|
||||||
<template v-for="log of rows" :key="log.id">
|
|
||||||
<QTimelineEntry
|
|
||||||
:avatar="`/api/Images/user/160x160/${log.userFk}/download?access_token=${token}`"
|
|
||||||
>
|
|
||||||
<template #subtitle>
|
|
||||||
{{ log.userName }} -
|
|
||||||
{{
|
|
||||||
toDate(log.created, {
|
|
||||||
dateStyle: 'medium',
|
|
||||||
timeStyle: 'short',
|
|
||||||
})
|
|
||||||
}}
|
|
||||||
</template>
|
</template>
|
||||||
<template #title>
|
|
||||||
<QChip :color="actionColor(log.action)">
|
|
||||||
{{ t(`actions.${log.action}`) }}
|
|
||||||
</QChip>
|
|
||||||
{{ t(`models.${log.model}`) }}
|
|
||||||
</template>
|
|
||||||
<QTable
|
|
||||||
:rows="log.changes"
|
|
||||||
:columns="columns"
|
|
||||||
row-key="property"
|
|
||||||
hide-pagination
|
|
||||||
dense
|
|
||||||
flat
|
|
||||||
>
|
|
||||||
<template #header="props">
|
|
||||||
<QTr :props="props">
|
|
||||||
<QTh
|
|
||||||
v-for="col in props.cols"
|
|
||||||
:key="col.name"
|
|
||||||
:props="props"
|
|
||||||
>
|
|
||||||
{{ t(col.label) }}
|
|
||||||
</QTh>
|
|
||||||
</QTr>
|
|
||||||
</template>
|
|
||||||
</QTable>
|
|
||||||
</QTimelineEntry>
|
|
||||||
</template>
|
|
||||||
</template>
|
|
||||||
</VnPaginate>
|
|
||||||
</QTimeline>
|
|
||||||
</div>
|
|
||||||
<Teleport v-if="stateStore.isHeaderMounted()" to="#actions-append">
|
|
||||||
<div class="row q-gutter-x-sm">
|
|
||||||
<QBtn flat @click="stateStore.toggleRightDrawer()" round dense icon="menu">
|
|
||||||
<QTooltip bottom anchor="bottom right">
|
|
||||||
{{ t('globals.collapseMenu') }}
|
|
||||||
</QTooltip>
|
|
||||||
</QBtn>
|
|
||||||
</div>
|
|
||||||
</Teleport>
|
|
||||||
<QDrawer v-model="stateStore.rightDrawer" show-if-above side="right" :width="300">
|
|
||||||
<QScrollArea class="fit text-grey-8">
|
|
||||||
<ClaimLogFilter data-key="ClaimLogs" />
|
|
||||||
</QScrollArea>
|
|
||||||
</QDrawer>
|
|
||||||
</template>
|
|
||||||
|
|
||||||
<style lang="scss" scoped>
|
|
||||||
.q-timeline {
|
|
||||||
width: 100%;
|
|
||||||
max-width: 80em;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<i18n>
|
|
||||||
en:
|
|
||||||
actions:
|
|
||||||
insert: Creates
|
|
||||||
update: Updates
|
|
||||||
delete: Deletes
|
|
||||||
models:
|
|
||||||
Claim: Claim
|
|
||||||
ClaimDms: Document
|
|
||||||
ClaimBeginning: Claimed Sales
|
|
||||||
ClaimObservation: Observation
|
|
||||||
properties:
|
|
||||||
id: ID
|
|
||||||
claimFk: Claim ID
|
|
||||||
saleFk: Sale ID
|
|
||||||
quantity: Quantity
|
|
||||||
observation: Observation
|
|
||||||
ticketCreated: Created
|
|
||||||
created: Created
|
|
||||||
isChargedToMana: Charged to mana
|
|
||||||
hasToPickUp: Has to pick Up
|
|
||||||
dmsFk: Document ID
|
|
||||||
text: Description
|
|
||||||
claimStateFk: Claim State
|
|
||||||
workerFk: Worker
|
|
||||||
clientFk: Customer
|
|
||||||
rma: RMA
|
|
||||||
responsibility: Responsibility
|
|
||||||
packages: Packages
|
|
||||||
es:
|
|
||||||
Audit logs: Registros de auditoría
|
|
||||||
Property: Propiedad
|
|
||||||
Before: Antes
|
|
||||||
After: Después
|
|
||||||
Yes: Si
|
|
||||||
Nothing: Nada
|
|
||||||
actions:
|
|
||||||
insert: Crea
|
|
||||||
update: Actualiza
|
|
||||||
delete: Elimina
|
|
||||||
models:
|
|
||||||
Claim: Reclamación
|
|
||||||
ClaimDms: Documento
|
|
||||||
ClaimBeginning: Línea reclamada
|
|
||||||
ClaimObservation: Observación
|
|
||||||
properties:
|
|
||||||
id: ID
|
|
||||||
claimFk: ID reclamación
|
|
||||||
saleFk: ID linea de venta
|
|
||||||
quantity: Cantidad
|
|
||||||
observation: Observación
|
|
||||||
ticketCreated: Creado
|
|
||||||
created: Creado
|
|
||||||
isChargedToMana: Cargado a maná
|
|
||||||
hasToPickUp: Se debe recoger
|
|
||||||
dmsFk: ID documento
|
|
||||||
text: Descripción
|
|
||||||
claimStateFk: Estado de la reclamación
|
|
||||||
workerFk: Trabajador
|
|
||||||
clientFk: Cliente
|
|
||||||
rma: RMA
|
|
||||||
responsibility: Responsabilidad
|
|
||||||
packages: Bultos
|
|
||||||
</i18n>
|
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
import { vi, describe, expect, it, beforeAll, afterEach } from 'vitest';
|
||||||
|
import { createWrapper } from 'app/test/vitest/helper';
|
||||||
|
import VnLog from 'src/components/common/VnLog.vue';
|
||||||
|
|
||||||
|
describe('VnLog', () => {
|
||||||
|
let vm;
|
||||||
|
beforeAll(() => {
|
||||||
|
vm = createWrapper(VnLog, {
|
||||||
|
global: {
|
||||||
|
stubs: ['FetchData', 'VnPaginate'],
|
||||||
|
mocks: {
|
||||||
|
fetch: vi.fn(),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
propsData: {
|
||||||
|
model: "Claim",
|
||||||
|
},
|
||||||
|
}).vm;
|
||||||
|
});
|
||||||
|
|
||||||
|
afterEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('formatValue()', () => {
|
||||||
|
it('should return Yes if has a true boolean', async () => {
|
||||||
|
const result = vm.formatValue(true);
|
||||||
|
|
||||||
|
expect(result).toEqual('Yes');
|
||||||
|
});
|
||||||
|
it('should return No if has a true boolean', async () => {
|
||||||
|
const result = vm.formatValue(false);
|
||||||
|
|
||||||
|
expect(result).toEqual('No');
|
||||||
|
});
|
||||||
|
it('should return Nothing if has no params', async () => {
|
||||||
|
const result = vm.formatValue();
|
||||||
|
|
||||||
|
expect(result).toEqual('Nothing');
|
||||||
|
});
|
||||||
|
it('should return a string from a string value', async () => {
|
||||||
|
const result = vm.formatValue('Something');
|
||||||
|
|
||||||
|
expect(result).toEqual(`"Something"`);
|
||||||
|
});
|
||||||
|
it('should call to format a date', async () => {
|
||||||
|
vi.mock('src/filters', () => ({
|
||||||
|
toDate: ()=>{
|
||||||
|
return "Date formatted"
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
|
||||||
|
const result = vm.formatValue('01-01-1970');
|
||||||
|
expect(result).toEqual("Date formatted");
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('actionColor()', () => {
|
||||||
|
it('should return positive if insert', async () => {
|
||||||
|
const result = vm.actionColor('insert');
|
||||||
|
|
||||||
|
expect(result).toEqual('positive');
|
||||||
|
});
|
||||||
|
it('should return positive if update', async () => {
|
||||||
|
const result = vm.actionColor('update');
|
||||||
|
|
||||||
|
expect(result).toEqual('positive');
|
||||||
|
});
|
||||||
|
it('should return negative if delete', async () => {
|
||||||
|
const result = vm.actionColor('delete');
|
||||||
|
|
||||||
|
expect(result).toEqual('negative');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
Loading…
Reference in New Issue