WIP: feat: refs #6726 add new section "logs" #903
|
@ -1,7 +1,7 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref, onUnmounted, watch } from 'vue';
|
import { ref, onUnmounted, computed } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import { useRoute, useRouter } from 'vue-router';
|
import { useRoute } from 'vue-router';
|
||||||
import axios from 'axios';
|
import axios from 'axios';
|
||||||
import { date } from 'quasar';
|
import { date } from 'quasar';
|
||||||
import { useStateStore } from 'stores/useStateStore';
|
import { useStateStore } from 'stores/useStateStore';
|
||||||
|
@ -11,16 +11,14 @@ import { useCapitalize } from 'src/composables/useCapitalize';
|
||||||
import { useValidator } from 'src/composables/useValidator';
|
import { useValidator } from 'src/composables/useValidator';
|
||||||
import VnAvatar from '../ui/VnAvatar.vue';
|
import VnAvatar from '../ui/VnAvatar.vue';
|
||||||
import VnJsonValue from '../common/VnJsonValue.vue';
|
import VnJsonValue from '../common/VnJsonValue.vue';
|
||||||
import FetchData from '../FetchData.vue';
|
|
||||||
import VnSelect from './VnSelect.vue';
|
|
||||||
import VnUserLink from '../ui/VnUserLink.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 stateStore = useStateStore();
|
||||||
const validationsStore = useValidator();
|
const validationsStore = useValidator();
|
||||||
const { models } = validationsStore;
|
const { models } = validationsStore;
|
||||||
const route = useRoute();
|
const route = useRoute();
|
||||||
const router = useRouter();
|
|
||||||
const { t } = useI18n();
|
const { t } = useI18n();
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
model: {
|
model: {
|
||||||
|
@ -35,8 +33,45 @@ const props = defineProps({
|
||||||
type: Function,
|
type: Function,
|
||||||
default: null,
|
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 = {
|
const filter = {
|
||||||
fields: [
|
fields: [
|
||||||
'id',
|
'id',
|
||||||
|
@ -67,72 +102,13 @@ const filter = {
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
],
|
],
|
||||||
where: { and: [{ originFk: route.params.id }] },
|
orderBy: ['originFk DESC', 'creationDate DESC'],
|
||||||
};
|
};
|
||||||
|
|
||||||
const paginate = ref();
|
onUnmounted(() => {
|
||||||
const actions = ref();
|
stateStore.rightDrawer = false;
|
||||||
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,
|
|
||||||
},
|
|
||||||
});
|
});
|
||||||
|
|
||||||
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) {
|
function castJsonValue(value) {
|
||||||
return typeof value === 'string' && validDate.test(value) ? new Date(value) : 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) {
|
function getLogTree(data) {
|
||||||
|
console.log('data: ', data);
|
||||||
|
if (!data) return;
|
||||||
|
|
||||||
const logs = [];
|
const logs = [];
|
||||||
let originLog = null;
|
let originLog = null;
|
||||||
let userLog = null;
|
let userLog = null;
|
||||||
|
@ -232,7 +211,7 @@ function getLogTree(data) {
|
||||||
|
|
||||||
async function openPointRecord(id, modelLog) {
|
async function openPointRecord(id, modelLog) {
|
||||||
pointRecord.value = null;
|
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 propNames = Object.keys(data);
|
||||||
const locale = validations[modelLog.model]?.locale || {};
|
const locale = validations[modelLog.model]?.locale || {};
|
||||||
pointRecord.value = parseProps(propNames, locale, data);
|
pointRecord.value = parseProps(propNames, locale, data);
|
||||||
|
@ -248,167 +227,25 @@ function filterByRecord(modelLog) {
|
||||||
searchInput.value = id;
|
searchInput.value = id;
|
||||||
selectedFilters.value.changedModelId = id;
|
selectedFilters.value.changedModelId = id;
|
||||||
selectedFilters.value.changedModel = model;
|
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>
|
</script>
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<VnTable
|
||||||
:url="`${props.model}Logs/${route.params.id}/models`"
|
v-if="modelName"
|
||||||
: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
|
|
||||||
ref="paginate"
|
ref="paginate"
|
||||||
:data-key="`${model}Log`"
|
data-key="vnLog"
|
||||||
:url="`${model}Logs`"
|
:url="`${modelName}Logs`"
|
||||||
:filter="filter"
|
|
||||||
:skeleton="false"
|
:skeleton="false"
|
||||||
auto-load
|
:user-filter="filter"
|
||||||
|
:auto-load="!!modelName || route.query.table"
|
||||||
@on-fetch="setLogTree"
|
@on-fetch="setLogTree"
|
||||||
search-url="logs"
|
:columns="[]"
|
||||||
|
:right-search="false"
|
||||||
|
search-url="table"
|
||||||
>
|
>
|
||||||
<template #body>
|
<template #body>
|
||||||
|
{{ paginate.params }}
|
||||||
<div
|
<div
|
||||||
class="column items-center logs origin-log q-mt-md"
|
class="column items-center logs origin-log q-mt-md"
|
||||||
v-for="(originLog, originLogIndex) in logTree"
|
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">
|
<QItem class="origin-info items-center q-my-md" v-if="logTree.length > 1">
|
||||||
<h6 class="origin-id text-grey">
|
<h6 class="origin-id text-grey">
|
||||||
{{ useCapitalize(validations[props.model].locale.name) }}
|
{{ useCapitalize(validations[modelName].locale.name) }}
|
||||||
#{{ originLog.originFk }}
|
#{{ originLog.originFk }}
|
||||||
</h6>
|
</h6>
|
||||||
<div class="line bg-grey"></div>
|
<div class="line bg-grey"></div>
|
||||||
|
@ -675,181 +512,10 @@ watch(
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
</VnPaginate>
|
</VnTable>
|
||||||
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
<Teleport to="#right-panel" v-if="stateStore.isHeaderMounted()">
|
||||||
<QList dense>
|
<VnLogFilter v-model="params" data-key="vnLog" :disable-model="disableModel" />
|
||||||
<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>
|
|
||||||
</Teleport>
|
</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>
|
</template>
|
||||||
<style lang="scss" scoped>
|
<style lang="scss" scoped>
|
||||||
.q-card {
|
.q-card {
|
||||||
|
@ -1038,77 +704,3 @@ watch(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</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>
|
|
||||||
|
|
|
@ -1,64 +1,220 @@
|
||||||
<script setup>
|
<script setup>
|
||||||
import { ref } from 'vue';
|
import { ref } from 'vue';
|
||||||
import { useI18n } from 'vue-i18n';
|
import { useI18n } from 'vue-i18n';
|
||||||
import FetchData from 'components/FetchData.vue';
|
|
||||||
import VnFilterPanel from 'src/components/ui/VnFilterPanel.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 { t } = useI18n();
|
||||||
|
const validationsStore = useValidator();
|
||||||
|
const { models } = validationsStore;
|
||||||
|
|
||||||
|
const modelParams = defineModel({ type: Object });
|
||||||
const props = defineProps({
|
const props = defineProps({
|
||||||
dataKey: {
|
dataKey: {
|
||||||
type: String,
|
type: String,
|
||||||
required: true,
|
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>
|
</script>
|
||||||
|
|
||||||
<template>
|
<template>
|
||||||
<FetchData
|
<FetchData
|
||||||
url="Workers/activeWithInheritedRole"
|
v-if="modelName && id"
|
||||||
:filter="{ where: { role: 'salesPerson' } }"
|
:url="`${modelName}Logs/${id}/models`"
|
||||||
@on-fetch="(data) => (workers = data)"
|
: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
|
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 }">
|
<template #tags="{ tag, formatFn }">
|
||||||
<div class="q-gutter-x-xs">
|
<div class="q-gutter-x-xs">
|
||||||
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
<strong>{{ t(`params.${tag.label}`) }}: </strong>
|
||||||
<span>{{ formatFn(tag.value) }}</span>
|
<span>{{ formatFn(tag.value) }}</span>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
<template #body="{ params, searchFn }">
|
<template #body="{ params }">
|
||||||
<QDate
|
<div class="q-gutter-y-sm q-px-sm">
|
||||||
v-model="params.created"
|
<QCard class="q-pa-xs q-mb-lg q-gutter-y-xs" flat bordered>
|
||||||
@update:model-value="searchFn()"
|
<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
|
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"
|
|
||||||
/>
|
/>
|
||||||
|
<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>
|
</QItemSection>
|
||||||
</QItem>
|
</QItem>
|
||||||
</template>
|
</template>
|
||||||
|
</VnSelect>
|
||||||
|
</QItemSection>
|
||||||
|
<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>
|
</VnFilterPanel>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
|
|
|
@ -85,7 +85,7 @@ const pagination = ref({
|
||||||
page: 1,
|
page: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
const arrayData = useArrayData(props.dataKey, {
|
let arrayData = useArrayData(props.dataKey, {
|
||||||
url: props.url,
|
url: props.url,
|
||||||
filter: props.filter,
|
filter: props.filter,
|
||||||
userFilter: props.userFilter,
|
userFilter: props.userFilter,
|
||||||
|
@ -97,7 +97,7 @@ const arrayData = useArrayData(props.dataKey, {
|
||||||
keepOpts: props.keepOpts,
|
keepOpts: props.keepOpts,
|
||||||
searchUrl: props.searchUrl,
|
searchUrl: props.searchUrl,
|
||||||
});
|
});
|
||||||
const store = arrayData.store;
|
let store = arrayData.store;
|
||||||
|
|
||||||
onMounted(async () => {
|
onMounted(async () => {
|
||||||
if (props.autoLoad) await fetch();
|
if (props.autoLoad) await fetch();
|
||||||
|
@ -120,14 +120,17 @@ watch(
|
||||||
|
|
||||||
watch(
|
watch(
|
||||||
() => [props.url, props.filter],
|
() => [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) => {
|
const addFilter = async (filter, params) => {
|
||||||
await arrayData.addFilter({ filter, params });
|
await arrayData.addFilter({ filter, params });
|
||||||
};
|
};
|
||||||
|
|
||||||
async function fetch(params) {
|
async function fetch(params) {
|
||||||
useArrayData(props.dataKey, params);
|
arrayData = useArrayData(props.dataKey, params);
|
||||||
|
store = arrayData.store;
|
||||||
arrayData.reset(['filter.skip', 'skip']);
|
arrayData.reset(['filter.skip', 'skip']);
|
||||||
await arrayData.fetch({ append: false });
|
await arrayData.fetch({ append: false });
|
||||||
if (!store.hasMoreData) isLoading.value = false;
|
if (!store.hasMoreData) isLoading.value = false;
|
||||||
|
|
|
@ -106,6 +106,7 @@ globals:
|
||||||
weight: Weight
|
weight: Weight
|
||||||
error: Ups! Something went wrong
|
error: Ups! Something went wrong
|
||||||
recalc: Recalculate
|
recalc: Recalculate
|
||||||
|
table: Table
|
||||||
pageTitles:
|
pageTitles:
|
||||||
logIn: Login
|
logIn: Login
|
||||||
addressEdit: Update address
|
addressEdit: Update address
|
||||||
|
@ -279,6 +280,8 @@ globals:
|
||||||
wasteRecalc: Waste recaclulate
|
wasteRecalc: Waste recaclulate
|
||||||
operator: Operator
|
operator: Operator
|
||||||
parking: Parking
|
parking: Parking
|
||||||
|
logs: Logs
|
||||||
|
logsList: Logs list
|
||||||
supplier: Supplier
|
supplier: Supplier
|
||||||
created: Created
|
created: Created
|
||||||
worker: Worker
|
worker: Worker
|
||||||
|
|
|
@ -108,6 +108,7 @@ globals:
|
||||||
weight: Peso
|
weight: Peso
|
||||||
error: ¡Ups! Algo salió mal
|
error: ¡Ups! Algo salió mal
|
||||||
recalc: Recalcular
|
recalc: Recalcular
|
||||||
|
table: Tabla
|
||||||
pageTitles:
|
pageTitles:
|
||||||
logIn: Inicio de sesión
|
logIn: Inicio de sesión
|
||||||
addressEdit: Modificar consignatario
|
addressEdit: Modificar consignatario
|
||||||
|
@ -283,6 +284,8 @@ globals:
|
||||||
wasteRecalc: Recalcular mermas
|
wasteRecalc: Recalcular mermas
|
||||||
operator: Operario
|
operator: Operario
|
||||||
parking: Parking
|
parking: Parking
|
||||||
|
logs: Historiales
|
||||||
|
logsList: Listado de historiales
|
||||||
supplier: Proveedor
|
supplier: Proveedor
|
||||||
created: Fecha creación
|
created: Fecha creación
|
||||||
worker: Trabajador
|
worker: Trabajador
|
||||||
|
|
|
@ -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>
|
|
@ -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
|
|
@ -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
|
|
@ -22,6 +22,7 @@ import Account from './account';
|
||||||
import Monitor from './monitor';
|
import Monitor from './monitor';
|
||||||
import MailAlias from './mailAlias';
|
import MailAlias from './mailAlias';
|
||||||
import Role from './role';
|
import Role from './role';
|
||||||
|
import Logs from './logs';
|
||||||
|
|
||||||
export default [
|
export default [
|
||||||
Item,
|
Item,
|
||||||
|
@ -48,4 +49,5 @@ export default [
|
||||||
MailAlias,
|
MailAlias,
|
||||||
Monitor,
|
Monitor,
|
||||||
Role,
|
Role,
|
||||||
|
Logs,
|
||||||
];
|
];
|
||||||
|
|
|
@ -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'),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
|
@ -22,6 +22,7 @@ import zone from 'src/router/modules/zone';
|
||||||
import account from './modules/account';
|
import account from './modules/account';
|
||||||
import monitor from 'src/router/modules/monitor';
|
import monitor from 'src/router/modules/monitor';
|
||||||
import mailAlias from './modules/mailAlias';
|
import mailAlias from './modules/mailAlias';
|
||||||
|
import logs from './modules/logs';
|
||||||
|
|
||||||
const routes = [
|
const routes = [
|
||||||
{
|
{
|
||||||
|
@ -97,6 +98,7 @@ const routes = [
|
||||||
account,
|
account,
|
||||||
role,
|
role,
|
||||||
mailAlias,
|
mailAlias,
|
||||||
|
logs,
|
||||||
{
|
{
|
||||||
path: '/:catchAll(.*)*',
|
path: '/:catchAll(.*)*',
|
||||||
name: 'NotFound',
|
name: 'NotFound',
|
||||||
|
|
|
@ -24,6 +24,7 @@ export const useNavigationStore = defineStore('navigationStore', () => {
|
||||||
'account',
|
'account',
|
||||||
'wagon',
|
'wagon',
|
||||||
'zone',
|
'zone',
|
||||||
|
'logs',
|
||||||
];
|
];
|
||||||
const pinnedModules = ref([]);
|
const pinnedModules = ref([]);
|
||||||
const acl = useAcl();
|
const acl = useAcl();
|
||||||
|
|
Loading…
Reference in New Issue