WIP: feat: refs #6726 add new section "logs" #903

Draft
alexm wants to merge 1 commits from 6726-LogSection into dev
12 changed files with 382 additions and 507 deletions
Showing only changes of commit 7487a2706c - Show all commits

View File

@ -1,7 +1,7 @@
<script setup>
import { ref, onUnmounted, watch } from 'vue';
import { ref, onUnmounted, computed } from 'vue';
import { useI18n } from 'vue-i18n';
import { useRoute, useRouter } from 'vue-router';
import { useRoute } from 'vue-router';
import axios from 'axios';
import { date } from 'quasar';
import { useStateStore } from 'stores/useStateStore';
@ -11,16 +11,14 @@ import { useCapitalize } from 'src/composables/useCapitalize';
import { useValidator } from 'src/composables/useValidator';
import VnAvatar from '../ui/VnAvatar.vue';
import VnJsonValue from '../common/VnJsonValue.vue';
import FetchData from '../FetchData.vue';
import VnSelect from './VnSelect.vue';
import VnUserLink from '../ui/VnUserLink.vue';
import VnPaginate from '../ui/VnPaginate.vue';
import VnLogFilter from './VnLogFilter.vue';
import VnTable from '../VnTable/VnTable.vue';
const stateStore = useStateStore();
const validationsStore = useValidator();
const { models } = validationsStore;
const route = useRoute();
const router = useRouter();
const { t } = useI18n();
const props = defineProps({
model: {
@ -35,8 +33,45 @@ const props = defineProps({
type: Function,
default: null,
},
disableModel: {
type: Boolean,
default: true,
},
});
const paginate = ref({});
const searchInput = ref();
const modelName = computed(() => params.value.model || props.model);
const selectedFilters = ref({});
const params = ref({ originFk: paginate.value?.params?.originFk ?? route.params.id });
let validations = models;
let pointRecord = ref(null);
let byRecord = ref(false);
const logTree = ref([]);
const actionsText = {
insert: 'Creates',
update: 'Edits',
delete: 'Deletes',
select: 'Accesses',
};
const actionsClass = {
insert: 'success',
update: 'warning',
delete: 'alert',
select: 'notice',
};
const actionsIcon = {
insert: 'add',
update: 'edit',
delete: 'remove',
select: 'visibility',
};
const validDate = new RegExp(
/^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])/.source +
/T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/.source
);
const filter = {
fields: [
'id',
@ -67,72 +102,13 @@ const filter = {
},
},
],
where: { and: [{ originFk: route.params.id }] },
orderBy: ['originFk DESC', 'creationDate DESC'],
};
const paginate = ref();
const actions = ref();
const changeInput = ref();
const searchInput = ref();
const userRadio = ref();
const userSelect = ref();
const dateFrom = ref();
const dateFromDialog = ref(false);
const dateTo = ref();
const dateToDialog = ref(false);
const selectedFilters = ref({});
const userTypes = [
{ label: 'All', value: undefined },
{ label: 'User', value: { neq: null } },
{ label: 'System', value: null },
];
const checkboxOptions = ref({
insert: {
label: 'Creates',
selected: false,
},
update: {
label: 'Edits',
selected: false,
},
delete: {
label: 'Deletes',
selected: false,
},
select: {
label: 'Accesses',
selected: false,
},
onUnmounted(() => {
stateStore.rightDrawer = false;
});
let validations = models;
let pointRecord = ref(null);
let byRecord = ref(false);
const logTree = ref([]);
const actionsText = {
insert: 'Creates',
update: 'Edits',
delete: 'Deletes',
select: 'Accesses',
};
const actionsClass = {
insert: 'success',
update: 'warning',
delete: 'alert',
select: 'notice',
};
const actionsIcon = {
insert: 'add',
update: 'edit',
delete: 'remove',
select: 'visibility',
};
const validDate = new RegExp(
/^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])/.source +
/T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?(Z)?$/.source
);
function castJsonValue(value) {
return typeof value === 'string' && validDate.test(value) ? new Date(value) : value;
}
@ -168,6 +144,9 @@ function parseProps(propNames, locale, vals, olds) {
}
function getLogTree(data) {
console.log('data: ', data);
if (!data) return;
const logs = [];
let originLog = null;
let userLog = null;
@ -232,7 +211,7 @@ function getLogTree(data) {
async function openPointRecord(id, modelLog) {
pointRecord.value = null;
const { data } = await axios.get(`${props.model}Logs/${id}/pitInstance`);
const { data } = await axios.get(`${modelName.value}Logs/${id}/pitInstance`);
const propNames = Object.keys(data);
const locale = validations[modelLog.model]?.locale || {};
pointRecord.value = parseProps(propNames, locale, data);
@ -248,167 +227,25 @@ function filterByRecord(modelLog) {
searchInput.value = id;
selectedFilters.value.changedModelId = id;
selectedFilters.value.changedModel = model;
applyFilter();
// applyFilter();
}
async function applyFilter() {
filter.where = { and: [] };
if (
!selectedFilters.value.changedModel ||
(!selectedFilters.value.changedModelValue &&
!selectedFilters.value.changedModelId)
)
byRecord.value = false;
if (!byRecord.value) filter.where.and.push({ originFk: route.params.id });
if (Object.keys(selectedFilters.value).length) {
filter.where.and.push(selectedFilters.value);
}
paginate.value.fetch(filter);
}
function setDate(type) {
let from = dateFrom.value
? date.formatDate(dateFrom.value.split('-').reverse().join('-'), 'YYYY-MM-DD')
: undefined;
from = date.adjustDate(from, { hour: 0, minute: 0, second: 0, millisecond: 0 }, true);
let to = dateTo.value
? date.formatDate(dateTo.value.split('-').reverse().join('-'), 'YYYY-MM-DD')
: date.formatDate(dateFrom.value.split('-').reverse().join('-'), 'YYYY-MM-DD');
to = date.adjustDate(
to,
{ hour: 21, minute: 59, second: 59, millisecond: 999 },
true
);
switch (type) {
case 'from':
return { between: [from, to] };
case 'to': {
if (dateFrom.value) {
return {
between: [from, to],
};
}
return { lte: to };
}
}
}
function selectFilter(type, dateType) {
const filter = {};
const actions = { inq: [] };
let reload = true;
if (type === 'search') {
if (/^\s*[0-9]+\s*$/.test(searchInput.value) || props.byRecord) {
selectedFilters.value.changedModelId = searchInput.value.trim();
} else if (!searchInput.value) {
selectedFilters.value.changedModelId = undefined;
selectedFilters.value.changedModelValue = undefined;
} else {
selectedFilters.value.changedModelValue = { like: `%${searchInput.value}%` };
}
}
if (type === 'action' && selectedFilters.value.changedModel === null) {
selectedFilters.value.changedModel = undefined;
}
if (type === 'userRadio') {
selectedFilters.value.userFk = userRadio.value;
}
if (type === 'change') {
if (changeInput.value)
selectedFilters.value.or = [
{ oldJson: { like: `%${changeInput.value}%` } },
{ newJson: { like: `%${changeInput.value}%` } },
{ description: { like: `%${changeInput.value}%` } },
];
else selectedFilters.value.or = undefined;
}
if (type === 'userSelect') {
selectedFilters.value.userFk =
userSelect.value !== null ? userSelect.value : undefined;
}
if (type === 'date') {
if (!dateFrom.value && !dateTo.value) {
selectedFilters.value.creationDate = undefined;
} else if (dateType === 'to') {
selectedFilters.value.creationDate = setDate('to');
} else if (dateType === 'from') {
selectedFilters.value.creationDate = setDate('from');
}
}
Object.keys(checkboxOptions.value).forEach((key) => {
if (checkboxOptions.value[key].selected) actions.inq.push(key);
});
selectedFilters.value.action = actions.inq.length ? actions : undefined;
Object.keys(selectedFilters.value).forEach((key) => {
if (selectedFilters.value[key]) filter[key] = selectedFilters.value[key];
});
if (reload) applyFilter(filter);
}
async function clearFilter() {
selectedFilters.value = {};
byRecord.value = false;
userSelect.value = undefined;
searchInput.value = undefined;
changeInput.value = undefined;
dateFrom.value = undefined;
dateTo.value = undefined;
userRadio.value = undefined;
Object.keys(checkboxOptions.value).forEach(
(opt) => (checkboxOptions.value[opt].selected = false)
);
await applyFilter();
}
onUnmounted(() => {
stateStore.rightDrawer = false;
});
watch(
() => router.currentRoute.value.params.id,
() => {
applyFilter();
}
);
</script>
<template>
<FetchData
:url="`${props.model}Logs/${route.params.id}/models`"
:filter="{ order: ['changedModel'] }"
@on-fetch="
(data) =>
(actions = data.map((item) => {
const changedModel = item.changedModel;
return {
locale: useCapitalize(
validations[changedModel]?.locale?.name ?? changedModel
),
value: changedModel,
};
}))
"
auto-load
/>
<VnPaginate
<VnTable
v-if="modelName"
ref="paginate"
:data-key="`${model}Log`"
:url="`${model}Logs`"
:filter="filter"
data-key="vnLog"
:url="`${modelName}Logs`"
:skeleton="false"
auto-load
:user-filter="filter"
:auto-load="!!modelName || route.query.table"
@on-fetch="setLogTree"
search-url="logs"
:columns="[]"
:right-search="false"
search-url="table"
>
<template #body>
{{ paginate.params }}
<div
class="column items-center logs origin-log q-mt-md"
v-for="(originLog, originLogIndex) in logTree"
@ -416,7 +253,7 @@ watch(
>
<QItem class="origin-info items-center q-my-md" v-if="logTree.length > 1">
<h6 class="origin-id text-grey">
{{ useCapitalize(validations[props.model].locale.name) }}
{{ useCapitalize(validations[modelName].locale.name) }}
#{{ originLog.originFk }}
</h6>
<div class="line bg-grey"></div>
@ -675,181 +512,10 @@ watch(
</div>
</div>
</template>
</VnPaginate>
</VnTable>
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
<QList dense>
<QSeparator />
<QItem class="q-mt-sm">
<QInput
:label="t('globals.search')"
v-model="searchInput"
class="full-width"
clearable
clear-icon="close"
@keyup.enter="() => selectFilter('search')"
@focusout="() => selectFilter('search')"
@clear="() => selectFilter('search')"
>
<template #append>
<QIcon name="info" class="cursor-pointer">
<QTooltip>{{ t('tooltips.search') }}</QTooltip>
</QIcon>
</template>
</QInput>
</QItem>
<QItem>
<VnSelect
class="full-width"
:label="t('globals.entity')"
v-model="selectedFilters.changedModel"
option-label="locale"
option-value="value"
:options="actions"
@update:model-value="selectFilter('action')"
hide-selected
/>
</QItem>
<QItem class="q-mt-sm">
<QOptionGroup
size="sm"
v-model="userRadio"
:options="userTypes"
color="primary"
@update:model-value="selectFilter('userRadio')"
right-label
>
<template #label="{ label }">
{{ t(`Users.${label}`) }}
</template>
</QOptionGroup>
</QItem>
<QItem class="q-mt-sm">
<QItemSection v-if="userRadio !== null">
<VnSelect
class="full-width"
:label="t('globals.user')"
v-model="userSelect"
option-label="name"
option-value="id"
:url="`${model}Logs/${$route.params.id}/editors`"
:fields="['id', 'nickname', 'name', 'image']"
sort-by="nickname"
@update:model-value="selectFilter('userSelect')"
hide-selected
>
<template #option="{ opt, itemProps }">
<QItem v-bind="itemProps" class="q-pa-xs row items-center">
<QItemSection class="col-3 items-center">
<VnAvatar :worker-id="opt.id" />
</QItemSection>
<QItemSection class="col-9 justify-center">
<span>{{ opt.name }}</span>
<span class="text-grey">{{ opt.nickname }}</span>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QItemSection>
</QItem>
<QItem class="q-mt-sm">
<QInput
:label="t('globals.changes')"
v-model="changeInput"
class="full-width"
clearable
clear-icon="close"
@keyup.enter="selectFilter('change')"
@focusout="selectFilter('change')"
@clear="selectFilter('change')"
>
<template #append>
<QIcon name="info" class="cursor-pointer">
<QTooltip max-width="250px">{{
t('tooltips.changes')
}}</QTooltip>
</QIcon>
</template>
</QInput>
</QItem>
<QItem
:class="index == 'create' ? 'q-mt-md' : 'q-mt-xs'"
v-for="(checkboxOption, index) in checkboxOptions"
:key="index"
>
<QCheckbox
size="sm"
v-model="checkboxOption.selected"
:label="t(`actions.${checkboxOption.label}`)"
@update:model-value="selectFilter"
/>
</QItem>
<QItem class="q-mt-sm">
<QInput
class="full-width"
:label="t('globals.date')"
@click="dateFromDialog = true"
@focus="(evt) => evt.target.blur()"
@clear="selectFilter('date', 'to')"
v-model="dateFrom"
clearable
clear-icon="close"
/>
</QItem>
<QItem class="q-mt-sm">
<QInput
class="full-width"
:label="t('to')"
@click="dateToDialog = true"
@focus="(evt) => evt.target.blur()"
@clear="selectFilter('date', 'from')"
v-model="dateTo"
clearable
clear-icon="close"
/>
</QItem>
</QList>
<VnLogFilter v-model="params" data-key="vnLog" :disable-model="disableModel" />
</Teleport>
<QDialog v-model="dateFromDialog">
<QDate
:years-in-month-view="false"
v-model="dateFrom"
dense
flat
minimal
@update:model-value="
(value) => {
dateFromDialog = false;
dateFrom = date.formatDate(value, 'DD-MM-YYYY');
selectFilter('date', 'from');
}
"
/>
</QDialog>
<QDialog v-model="dateToDialog">
<QDate
v-model="dateTo"
dense
flat
minimal
@update:model-value="
(value) => {
dateToDialog = false;
dateTo = date.formatDate(value, 'DD-MM-YYYY');
selectFilter('date', 'to');
}
"
/>
</QDialog>
<QPageSticky position="bottom-right" :offset="[25, 25]">
<QBtn
v-if="Object.values(selectedFilters).some((filter) => filter !== undefined)"
color="primary"
icon="filter_alt_off"
size="md"
round
@click="clearFilter"
/>
</QPageSticky>
</template>
<style lang="scss" scoped>
.q-card {
@ -1038,77 +704,3 @@ watch(
}
}
</style>
<i18n>
en:
to: To
pointRecord: View record at this point in time
recordChanges: show all record changes
tooltips:
search: Search by id or concept
changes: Search by changes
actions:
Creates: Creates
Edits: Edits
Deletes: Deletes
Accesses: Accesses
Users:
User: Usuario
All: Todo
System: Sistema
properties:
id: ID
claimFk: Claim ID
saleFk: Sale ID
quantity: Quantity
observation: Observation
ticketCreated: Created
created: Created
isChargedToMana: Charged to mana
pickup: Type of pickup
dmsFk: Document ID
text: Description
claimStateFk: Claim State
workerFk: Worker
clientFk: Customer
responsibility: Responsibility
packages: Packages
es:
to: Hasta
pointRecord: Ver el registro en este punto
recordChanges: Mostrar todos los cambios realizados en el registro
tooltips:
search: Buscar por identificador o concepto
changes: Buscar por cambios. Los atributos deben buscarse por su nombre interno, para obtenerlo situar el cursor sobre el atributo.
Audit logs: Historial
Property: Propiedad
Before: Antes
After: Después
Yes: Si
Nothing: Nada
actions:
Creates: Crea
Edits: Modifica
Deletes: Elimina
Accesses: Accede
Users:
User: Usuario
All: Todo
System: Sistema
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á
pickup: Se debe recoger
dmsFk: ID documento
text: Descripción
claimStateFk: Estado de la reclamación
workerFk: Trabajador
clientFk: Cliente
responsibility: Responsabilidad
packages: Bultos
</i18n>

View File

@ -1,63 +1,219 @@
<script setup>
import { ref } from 'vue';
import { useI18n } from 'vue-i18n';
import FetchData from 'components/FetchData.vue';
import VnFilterPanel from 'src/components/ui/VnFilterPanel.vue';
import VnInput from './VnInput.vue';
import VnSelect from './VnSelect.vue';
import { useValidator } from 'src/composables/useValidator';
import VnAvatar from '../ui/VnAvatar.vue';
import FetchData from '../FetchData.vue';
import VnInputDate from './VnInputDate.vue';
const { t } = useI18n();
const validationsStore = useValidator();
const { models } = validationsStore;
const modelParams = defineModel({ type: Object });
const props = defineProps({
dataKey: {
type: String,
required: true,
},
disableModel: {
type: Boolean,
default: true,
},
});
const workers = ref();
const userTypes = [
{ label: 'All', value: undefined },
{ label: 'User', value: { neq: null } },
{ label: 'System', value: null },
];
const actions = ref();
const checkboxOptions = ref({
insert: {
label: 'Creates',
selected: false,
},
update: {
label: 'Edits',
selected: false,
},
delete: {
label: 'Deletes',
selected: false,
},
select: {
label: 'Accesses',
selected: false,
},
});
const exprBuilder = (param, value) => {
if (param == 'originFk') return { originFk: value };
};
</script>
<template>
<FetchData
url="Workers/activeWithInheritedRole"
:filter="{ where: { role: 'salesPerson' } }"
@on-fetch="(data) => (workers = data)"
v-if="modelName && id"
:url="`${modelName}Logs/${id}/models`"
:filter="{ order: ['changedModel'] }"
@on-fetch="
(data) =>
(actions = data.map((item) => {
const changedModel = item.changedModel;
return {
locale: useCapitalize(
validations[changedModel]?.locale?.name ?? changedModel
),
value: changedModel,
};
}))
"
auto-load
/>
<VnFilterPanel :data-key="props.dataKey" :search-button="true">
{{ modelParams }}
<VnFilterPanel
v-model="modelParams"
:data-key="props.dataKey"
:search-button="true"
:hidden-tags="disableModel && ['modelName', 'id']"
search-url="table"
:redirect="false"
:expr-builder="exprBuilder"
>
<template #tags="{ tag, formatFn }">
<div class="q-gutter-x-xs">
<strong>{{ t(`params.${tag.label}`) }}: </strong>
<span>{{ formatFn(tag.value) }}</span>
</div>
</template>
<template #body="{ params, searchFn }">
<QDate
v-model="params.created"
@update:model-value="searchFn()"
dense
flat
minimal
>
</QDate>
<QSeparator />
<QItem>
<QItemSection v-if="!workers">
<QSkeleton type="QInput" class="full-width" />
</QItemSection>
<QItemSection v-if="workers">
<QSelect
:label="t('User')"
v-model="params.userFk"
@update:model-value="searchFn()"
:options="workers"
option-value="id"
option-label="name"
emit-value
map-options
use-input
:input-debounce="0"
<template #body="{ params }">
<div class="q-gutter-y-sm q-px-sm">
<QCard class="q-pa-xs q-mb-lg q-gutter-y-xs" flat bordered>
<VnSelect
:label="$t('globals.table')"
:options="
Object.keys(models)
?.filter((key) => key.endsWith('Log'))
?.map((key) => key.slice(0, -3))
"
v-model="params.model"
:disable="props.disableModel"
filled
dense
/>
<VnInput
:label="$t('globals.id')"
v-model="params.originFk"
:disable="props.disableModel"
filled
dense
/>
</QCard>
<VnInput
:label="t('globals.search')"
v-model="params.searchInput"
filled
dense
>
<template #append>
<QIcon name="info" class="cursor-pointer">
<QTooltip>{{ t('tooltips.search') }}</QTooltip>
</QIcon>
</template>
</VnInput>
<VnSelect
:label="t('globals.entity')"
v-model="params.changedModel"
option-label="locale"
option-value="value"
:options="actions"
hide-selected
filled
dense
/>
<QOptionGroup
size="sm"
v-model="params.userRadio"
:options="userTypes"
color="primary"
right-label
filled
dense
>
<template #label="{ label }">
{{ t(`Users.${label}`) }}
</template>
</QOptionGroup>
<QItemSection v-if="params.userRadio !== null">
<VnSelect
:label="t('globals.user')"
v-model="params.userSelect"
option-label="name"
option-value="id"
:url="`${params.modelName}Logs/${params.id}/editors`"
:fields="['id', 'nickname', 'name', 'image']"
sort-by="nickname"
hide-selected
filled
dense
>
<template #option="{ opt, itemProps }">
<QItem v-bind="itemProps" class="q-pa-xs row items-center">
<QItemSection class="col-3 items-center">
<VnAvatar :worker-id="opt.id" />
</QItemSection>
<QItemSection class="col-9 justify-center">
<span>{{ opt.name }}</span>
<span class="text-grey">{{ opt.nickname }}</span>
</QItemSection>
</QItem>
</template>
</VnSelect>
</QItemSection>
</QItem>
<VnInput
:label="t('globals.changes')"
v-model="params.changeInput"
filled
dense
>
<template #append>
<QIcon name="info" class="cursor-pointer">
<QTooltip max-width="250px">{{
t('tooltips.changes')
}}</QTooltip>
</QIcon>
</template>
</VnInput>
<div v-for="(checkboxOption, index) in checkboxOptions" :key="index">
<QCheckbox
size="sm"
v-model="params.checkboxOption"
:label="t(`actions.${checkboxOption.label}`)"
filled
dense
/>
</div>
<VnInputDate
:label="t('globals.date')"
@click="dateFromDialog = true"
@focus="(evt) => evt.target.blur()"
v-model="params.dateFrom"
filled
dense
/>
<VnInputDate
:label="t('to')"
@click="dateToDialog = true"
@focus="(evt) => evt.target.blur()"
v-model="params.dateTo"
filled
dense
/>
</div>
</template>
</VnFilterPanel>
</template>

View File

@ -85,7 +85,7 @@ const pagination = ref({
page: 1,
});
const arrayData = useArrayData(props.dataKey, {
let arrayData = useArrayData(props.dataKey, {
url: props.url,
filter: props.filter,
userFilter: props.userFilter,
@ -97,7 +97,7 @@ const arrayData = useArrayData(props.dataKey, {
keepOpts: props.keepOpts,
searchUrl: props.searchUrl,
});
const store = arrayData.store;
let store = arrayData.store;
onMounted(async () => {
if (props.autoLoad) await fetch();
@ -120,14 +120,17 @@ watch(
watch(
() => [props.url, props.filter],
([url, filter]) => mounted.value && fetch({ url, filter })
async ([url, filter]) => {
mounted.value && (await fetch({ url, filter }));
}
);
const addFilter = async (filter, params) => {
await arrayData.addFilter({ filter, params });
};
async function fetch(params) {
useArrayData(props.dataKey, params);
arrayData = useArrayData(props.dataKey, params);
store = arrayData.store;
arrayData.reset(['filter.skip', 'skip']);
await arrayData.fetch({ append: false });
if (!store.hasMoreData) isLoading.value = false;

View File

@ -106,6 +106,7 @@ globals:
weight: Weight
error: Ups! Something went wrong
recalc: Recalculate
table: Table
pageTitles:
logIn: Login
addressEdit: Update address
@ -279,6 +280,8 @@ globals:
wasteRecalc: Waste recaclulate
operator: Operator
parking: Parking
logs: Logs
logsList: Logs list
supplier: Supplier
created: Created
worker: Worker

View File

@ -108,6 +108,7 @@ globals:
weight: Peso
error: ¡Ups! Algo salió mal
recalc: Recalcular
table: Tabla
pageTitles:
logIn: Inicio de sesión
addressEdit: Modificar consignatario
@ -283,6 +284,8 @@ globals:
wasteRecalc: Recalcular mermas
operator: Operario
parking: Parking
logs: Historiales
logsList: Listado de historiales
supplier: Proveedor
created: Fecha creación
worker: Trabajador

View File

@ -0,0 +1,8 @@
<script setup>
import RightMenu from 'src/components/common/RightMenu.vue';
import VnLog from 'src/components/common/VnLog.vue';
</script>
<template>
<RightMenu />
<VnLog :disable-model="false" />
</template>

View File

@ -0,0 +1,32 @@
to: To
pointRecord: View record at this point in time
recordChanges: show all record changes
tooltips:
search: Search by id or concept
changes: Search by changes
actions:
Creates: Creates
Edits: Edits
Deletes: Deletes
Accesses: Accesses
Users:
User: Usuario
All: Todo
System: Sistema
properties:
id: ID
claimFk: Claim ID
saleFk: Sale ID
quantity: Quantity
observation: Observation
ticketCreated: Created
created: Created
isChargedToMana: Charged to mana
pickup: Type of pickup
dmsFk: Document ID
text: Description
claimStateFk: Claim State
workerFk: Worker
clientFk: Customer
responsibility: Responsibility
packages: Packages

View File

@ -0,0 +1,38 @@
to: Hasta
pointRecord: Ver el registro en este punto
recordChanges: Mostrar todos los cambios realizados en el registro
tooltips:
search: Buscar por identificador o concepto
changes: Buscar por cambios. Los atributos deben buscarse por su nombre interno, para obtenerlo situar el cursor sobre el atributo.
Audit logs: Historial
Property: Propiedad
Before: Antes
After: Después
Yes: Si
Nothing: Nada
actions:
Creates: Crea
Edits: Modifica
Deletes: Elimina
Accesses: Accede
Users:
User: Usuario
All: Todo
System: Sistema
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á
pickup: Se debe recoger
dmsFk: ID documento
text: Descripción
claimStateFk: Estado de la reclamación
workerFk: Trabajador
clientFk: Cliente
responsibility: Responsabilidad
packages: Bultos

View File

@ -22,6 +22,7 @@ import Account from './account';
import Monitor from './monitor';
import MailAlias from './mailAlias';
import Role from './role';
import Logs from './logs';
export default [
Item,
@ -48,4 +49,5 @@ export default [
MailAlias,
Monitor,
Role,
Logs,
];

View File

@ -0,0 +1,35 @@
import { RouterView } from 'vue-router';
export default {
path: '/logs',
name: 'Logs',
meta: {
title: 'logs',
icon: 'vn:History',
moduleName: 'Logs',
},
component: RouterView,
redirect: { name: 'LogsMain' },
menus: {
main: ['LogsList'],
},
children: [
{
path: '/logs',
name: 'LogsMain',
component: () => import('src/components/common/VnSectionMain.vue'),
redirect: { name: 'LogsList' },
children: [
{
path: 'list',
name: 'LogsList',
meta: {
title: 'logsList',
icon: 'vn:History',
},
component: () => import('src/pages/Logs/LogsList.vue'),
},
],
},
],
};

View File

@ -22,6 +22,7 @@ import zone from 'src/router/modules/zone';
import account from './modules/account';
import monitor from 'src/router/modules/monitor';
import mailAlias from './modules/mailAlias';
import logs from './modules/logs';
const routes = [
{
@ -97,6 +98,7 @@ const routes = [
account,
role,
mailAlias,
logs,
{
path: '/:catchAll(.*)*',
name: 'NotFound',

View File

@ -24,6 +24,7 @@ export const useNavigationStore = defineStore('navigationStore', () => {
'account',
'wagon',
'zone',
'logs',
];
const pinnedModules = ref([]);
const acl = useAcl();