Merge branch 'dev' of https://gitea.verdnatura.es/verdnatura/salix-front into 8630-refactorRouteSectionsAndLocalizations
gitea/salix-front/pipeline/pr-dev There was a failure building this commit Details

This commit is contained in:
Jose Antonio Tubau 2025-03-12 08:33:50 +01:00
commit 579b15e6d7
22 changed files with 105 additions and 101 deletions

View File

@ -188,7 +188,7 @@ const selectItem = ({ id }) => {
>
<template #body-cell-id="{ row }">
<QTd auto-width @click.stop>
<QBtn flat color="blue">{{ row.id }}</QBtn>
<QBtn flat class="link">{{ row.id }}</QBtn>
<ItemDescriptorProxy :id="row.id" />
</QTd>
</template>

View File

@ -196,7 +196,7 @@ const selectTravel = ({ id }) => {
>
<template #body-cell-id="{ row }">
<QTd auto-width @click.stop data-cy="travelFk-travel-form">
<QBtn flat color="blue">{{ row.id }}</QBtn>
<QBtn flat class="link">{{ row.id }}</QBtn>
<TravelDescriptorProxy :id="row.id" />
</QTd>
</template>

View File

@ -77,6 +77,7 @@ watch(
function findMatches(search, item) {
const matches = [];
function findRoute(search, item) {
if (!item?.children) return;
for (const child of item.children) {
if (search?.indexOf(child.name) > -1) {
matches.push(child);
@ -92,7 +93,7 @@ function findMatches(search, item) {
}
function addChildren(module, route, parent) {
const menus = route?.meta?.menu ?? route?.menus?.[props.source]; //backwards compatible
const menus = route?.meta?.menu;
if (!menus) return;
const matches = findMatches(menus, route);
@ -107,11 +108,7 @@ function getRoutes() {
main: getMainRoutes,
card: getCardRoutes,
};
try {
handleRoutes[props.source]();
} catch (error) {
throw new Error(`Method is not defined`);
}
handleRoutes[props.source]();
}
function getMainRoutes() {
const modules = Object.assign([], navigation.getModules().value);
@ -122,7 +119,6 @@ function getMainRoutes() {
);
if (!moduleDef) continue;
item.children = [];
addChildren(item.module, moduleDef, item.children);
}
@ -132,21 +128,16 @@ function getMainRoutes() {
function getCardRoutes() {
const currentRoute = route.matched[1];
const currentModule = toLowerCamel(currentRoute.name);
let moduleDef = routes.find((route) => toLowerCamel(route.name) === currentModule);
let moduleDef;
if (!moduleDef) return;
if (!moduleDef?.menus) moduleDef = betaGetRoutes();
addChildren(currentModule, moduleDef, items.value);
}
function betaGetRoutes() {
let menuRoute;
let index = route.matched.length - 1;
while (!menuRoute && index > 0) {
if (route.matched[index]?.meta?.menu) menuRoute = route.matched[index];
while (!moduleDef && index > 0) {
if (route.matched[index]?.meta?.menu) moduleDef = route.matched[index];
index--;
}
return menuRoute;
if (!moduleDef) return;
addChildren(currentModule, moduleDef, items.value);
}
async function togglePinned(item, event) {

View File

@ -15,10 +15,7 @@ vi.mock('src/router/modules', () => ({
meta: {
title: 'customers',
icon: 'vn:client',
},
menus: {
main: ['CustomerList', 'CustomerCreate'],
card: ['CustomerBasicData'],
menu: ['CustomerList', 'CustomerCreate'],
},
children: [
{
@ -98,7 +95,7 @@ vi.spyOn(vueRouter, 'useRoute').mockReturnValue({
icon: 'vn:client',
moduleName: 'Customer',
keyBinding: 'c',
menu: 'customer',
menu: ['customer'],
},
},
],
@ -260,15 +257,6 @@ describe('Leftmenu as main', () => {
});
});
it('should handle a single matched route with a menu', () => {
const route = {
matched: [{ meta: { menu: 'customer' } }],
};
const result = vm.betaGetRoutes();
expect(result.meta.menu).toEqual(route.matched[0].meta.menu);
});
it('should get routes for main source', () => {
vm.props.source = 'main';
vm.getRoutes();
@ -351,8 +339,9 @@ describe('addChildren', () => {
it('should handle routes with no meta menu', () => {
const route = {
meta: {},
menus: {},
meta: {
menu: [],
},
};
const parent = [];

View File

@ -15,6 +15,7 @@ body.body--light {
--vn-empty-tag: #acacac;
--vn-black-text-color: black;
--vn-text-color-contrast: white;
--vn-link-color: #1e90ff;
background-color: var(--vn-page-color);
@ -38,6 +39,7 @@ body.body--dark {
--vn-empty-tag: #2d2d2d;
--vn-black-text-color: black;
--vn-text-color-contrast: black;
--vn-link-color: #66bfff;
background-color: var(--vn-page-color);
@ -49,7 +51,7 @@ a {
}
.link {
color: $color-link;
color: var(--vn-link-color);
cursor: pointer;
&--white {
@ -58,14 +60,14 @@ a {
}
.tx-color-link {
color: $color-link !important;
color: var(--vn-link-color) !important;
}
.tx-color-font {
color: $color-link !important;
color: var(--vn-link-color) !important;
}
.header-link {
color: $color-link !important;
color: var(--vn-link-color) !important;
cursor: pointer;
border-bottom: solid $primary;
border-width: 2px;

View File

@ -24,7 +24,6 @@ $alert: $negative;
$white: #fff;
$dark: #3d3d3d;
// custom
$color-link: #66bfff;
$color-spacer-light: #a3a3a31f;
$color-spacer: #7979794d;
$border-thin-light: 1px solid $color-spacer-light;

View File

@ -532,6 +532,7 @@ ticket:
customerCard: Customer card
ticketList: Ticket List
newOrder: New Order
ticketClaimed: Claimed ticket
boxing:
expedition: Expedition
created: Created

View File

@ -539,6 +539,7 @@ ticket:
customerCard: Ficha del cliente
ticketList: Listado de tickets
newOrder: Nuevo pedido
ticketClaimed: Ticket reclamado
boxing:
expedition: Expedición
created: Creado

View File

@ -5,6 +5,7 @@ import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const route = useRoute();
const { t } = useI18n();
@ -27,13 +28,10 @@ const entityId = computed(() => $props.id || route.params.id);
<template #body="{ entity: alias }">
<QCard class="vn-one">
<QCardSection class="q-pa-none">
<router-link
:to="{ name: 'AliasBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" />
</router-link>
<VnTitle
:url="`#/account/alias/${entityId}/basic-data`"
:text="t('globals.summary.basicData')"
/>
</QCardSection>
<VnLv :label="t('role.id')" :value="alias.id" />
<VnLv :label="t('role.description')" :value="alias.description" />

View File

@ -5,6 +5,7 @@ import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import filter from './AccountFilter.js';
import AccountDescriptorMenu from './AccountDescriptorMenu.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const $props = defineProps({ id: { type: Number, default: 0 } });
@ -26,13 +27,10 @@ const entityId = computed(() => $props.id || route.params.id);
<template #body="{ entity }">
<QCard class="vn-one">
<QCardSection class="q-pa-none">
<router-link
:to="{ name: 'AccountBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ $t('globals.pageTitles.basicData') }}
<QIcon name="open_in_new" />
</router-link>
<VnTitle
:url="`#/account/${entityId}/basic-data`"
:text="$t('globals.pageTitles.basicData')"
/>
</QCardSection>
<VnLv :label="$t('account.card.nickname')" :value="entity.name" />
<VnLv :label="$t('account.card.role')" :value="entity.role?.name" />

View File

@ -4,6 +4,7 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const route = useRoute();
const { t } = useI18n();
@ -29,13 +30,10 @@ const entityId = computed(() => $props.id || route.params.id);
<template #body="{ entity }">
<QCard class="vn-one">
<QCardSection class="q-pa-none">
<a
class="header header-link"
:href="`#/VnUser/${entityId}/basic-data`"
>
{{ t('globals.pageTitles.basicData') }}
<QIcon name="open_in_new" />
</a>
<VnTitle
:url="`#/account/role/${entityId}/basic-data`"
:text="$t('globals.pageTitles.basicData')"
/>
</QCardSection>
<VnLv :label="t('role.id')" :value="entity.id" />
<VnLv :label="t('globals.name')" :value="entity.name" />

View File

@ -271,7 +271,7 @@ function claimUrl(section) {
</VnLv>
<VnLv v-if="$route.name != 'ClaimSummary'" :label="t('claim.customer')">
<template #value>
<span class="link cursor-pointer">
<span class="link">
{{ claim.client?.name }}
<CustomerDescriptorProxy :id="claim.clientFk" />
</span>

View File

@ -86,12 +86,12 @@ const tableColumnComponents = {
},
file: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
props: () => ({ flat: true }),
event: ({ row }) => downloadFile(row.dmsFk),
},
employee: {
component: QBtn,
props: () => ({ flat: true, color: 'blue' }),
props: () => ({ flat: true }),
event: () => {},
},
created: {
@ -214,8 +214,17 @@ const toCustomerFileManagementCreate = () => {
v-bind="tableColumnComponents[props.col.name].props(props)"
>
<template v-if="props.col.name !== 'original'">
{{ props.value }}
<span
:class="{
link:
props.col.name === 'employee' ||
props.col.name === 'file',
}"
>
{{ props.value }}
</span>
</template>
<WorkerDescriptorProxy
:id="props.row.dms.workerFk"
v-if="props.col.name === 'employee'"

View File

@ -7,6 +7,7 @@ import filter from './ItemTypeFilter.js';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'src/components/ui/VnLv.vue';
import VnToSummary from 'src/components/ui/VnToSummary.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
onUpdated(() => summaryRef.value.fetch());
@ -62,13 +63,10 @@ async function setItemTypeData(data) {
</template>
<template #body>
<QCard class="vn-one">
<router-link
:to="{ name: 'ItemTypeBasicData', params: { id: entityId } }"
class="header header-link"
>
{{ t('globals.summary.basicData') }}
<QIcon name="open_in_new" />
</router-link>
<VnTitle
:url="`#/item/item-type/${entityId}/basic-data`"
:text="$t('globals.summary.basicData')"
/>
<VnLv :label="t('itemType.summary.id')" :value="itemType.id" />
<VnLv :label="t('itemType.shared.code')" :value="itemType.code" />
<VnLv :label="t('itemType.shared.name')" :value="itemType.name" />

View File

@ -168,7 +168,7 @@ const ticketColumns = ref([
<VnLv
:label="t('route.summary.volume')"
:value="`${dashIfEmpty(entity?.route?.m3)} / ${dashIfEmpty(
entity?.route?.vehicle?.m3
entity?.route?.vehicle?.m3,
)} `"
/>
<VnLv
@ -221,7 +221,7 @@ const ticketColumns = ref([
<template #body-cell-city="{ value, row }">
<QTd auto-width>
<span
class="link cursor-pointer"
class="link"
@click="openBuscaman(entity?.route?.vehicleFk, [row])"
>
{{ value }}
@ -230,7 +230,7 @@ const ticketColumns = ref([
</template>
<template #body-cell-client="{ value, row }">
<QTd auto-width>
<span class="link cursor-pointer">
<span class="link">
{{ value }}
<CustomerDescriptorProxy :id="row?.clientFk" />
</span>
@ -238,7 +238,7 @@ const ticketColumns = ref([
</template>
<template #body-cell-ticket="{ value, row }">
<QTd auto-width class="text-center">
<span class="link cursor-pointer">
<span class="link">
{{ value }}
<TicketDescriptorProxy :id="row?.id" />
</span>

View File

@ -6,6 +6,7 @@ import VnLv from 'components/ui/VnLv.vue';
import VnUserLink from 'components/ui/VnUserLink.vue';
import filter from './ShelvingFilter.js';
import ShelvingDescriptorMenu from './ShelvingDescriptorMenu.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const $props = defineProps({
id: {
@ -38,13 +39,10 @@ const entityId = computed(() => $props.id || route.params.id);
</template>
<template #body="{ entity }">
<QCard class="vn-one">
<RouterLink
class="header header-link"
:to="{ name: 'ShelvingBasicData', params: { id: entityId } }"
>
{{ $t('globals.pageTitles.basicData') }}
<QIcon name="open_in_new" />
</RouterLink>
<VnTitle
:url="`#/shelving/${entityId}/basic-data`"
:text="$t('globals.pageTitles.basicData')"
/>
<VnLv :label="$t('globals.code')" :value="entity.code" />
<VnLv
:label="$t('shelving.list.parking')"

View File

@ -4,6 +4,7 @@ import { useRoute } from 'vue-router';
import { useI18n } from 'vue-i18n';
import CardSummary from 'components/ui/CardSummary.vue';
import VnLv from 'components/ui/VnLv.vue';
import VnTitle from 'src/components/common/VnTitle.vue';
const $props = defineProps({
id: {
@ -28,13 +29,10 @@ const filter = {
<template #body="{ entity }">
<QCard class="vn-one">
<QCardSection class="q-pa-none">
<a
class="header header-link"
:href="`#/parking/${entityId}/basic-data`"
>
{{ t('globals.pageTitles.basicData') }}
<QIcon name="open_in_new" />
</a>
<VnTitle
:url="`#/shelving/parking/${entityId}/basic-data`"
:text="$t('globals.pageTitles.basicData')"
/>
</QCardSection>
<VnLv :label="t('globals.code')" :value="entity.code" />
<VnLv

View File

@ -203,7 +203,7 @@ onMounted(async () => {
</QTr>
<QTr v-for="(buy, index) in row.buys" :key="index">
<QTd no-hover>
<QBtn flat color="blue" dense no-caps>{{ buy.itemName }}</QBtn>
<QBtn flat class="link" dense no-caps>{{ buy.itemName }}</QBtn>
<ItemDescriptorProxy :id="buy.itemFk" />
</QTd>

View File

@ -11,6 +11,7 @@ import { toDateTimeFormat } from 'src/filters/date';
import filter from './TicketFilter.js';
import FetchData from 'src/components/FetchData.vue';
import TicketProblems from 'src/components/TicketProblems.vue';
import axios from 'axios';
const $props = defineProps({
id: {
@ -31,23 +32,37 @@ const entityId = computed(() => {
return $props.id || route.params.id;
});
const problems = ref({});
const originalTicket = ref();
function ticketFilter(ticket) {
return JSON.stringify({ clientFk: ticket.clientFk });
}
async function getClaims() {
const userFilter = { where: { refundTicketFk: entityId.value } };
const { data } = await axios.get(`TicketRefunds`, {
params: { filter: JSON.stringify(userFilter) },
});
if (!data) return;
originalTicket.value = data[0]?.originalTicketFk;
}
async function getProblems() {
const { data } = await axios.get(`Tickets/${entityId.value}/getTicketProblems`);
if (!data) return;
problems.value = data[0];
}
function getInfo() {
getClaims();
getProblems();
}
</script>
<template>
<FetchData
:url="`Tickets/${entityId}/getTicketProblems`"
auto-load
@on-fetch="(data) => ([problems] = data)"
/>
<CardDescriptor
:url="`Tickets/${entityId}`"
:filter="filter"
data-key="Ticket"
:summary="$props.summary"
@on-fetch="getInfo"
width="lg-width"
>
<template #menu="{ entity }">
@ -129,6 +144,15 @@ function ticketFilter(ticket) {
>
<QTooltip>{{ t('ticket.card.newOrder') }}</QTooltip>
</QBtn>
<QBtn
v-if="originalTicket"
size="md"
icon="vn:claims"
color="primary"
:to="{ name: 'TicketCard', params: { id: originalTicket } }"
>
<QTooltip>{{ t('ticket.card.ticketClaimed') }}</QTooltip>
</QBtn>
</QCardActions>
</template>
</CardDescriptor>

View File

@ -225,7 +225,7 @@ function onBuysFetched(data) {
/>
</div>
<div class="flex column left" style="align-items: flex-start">
<QBtn flat class="link text-blue">
<QBtn flat class="link">
{{ item?.longName ?? item.name }}
<ItemDescriptorProxy :id="entityId" />
<FetchedTags class="q-ml-md" :item="item" :columns="7" />

View File

@ -2,7 +2,7 @@
describe('ParkingList', () => {
const searchbar = '#searchbar input';
const firstCard = ':nth-child(1) > .q-card > .no-margin > .q-py-none';
const summaryHeader = '.summaryBody .header';
const summaryHeader = '.header-link';
beforeEach(() => {
cy.viewport(1920, 1080);

View File

@ -16,8 +16,8 @@ describe('ShelvingList', () => {
it('should redirect from preview to basic-data', () => {
cy.typeSearchbar('{enter}');
cy.dataCy('cardBtn').eq(0).click();
cy.get('.q-card > .header').click();
cy.url().should('include', '/shelving/1/basic-data');
cy.get('.summaryHeader > .header > .q-icon').click();
cy.url().should('include', '/shelving/1/summary');
});
it('should filter and redirect if only one result', () => {