diff --git a/CHANGELOG.md b/CHANGELOG.md index 07674af54..43bd6da77 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,10 +5,16 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [2418.01] + ## [2416.01] - 2024-04-18 ### Added +### Fixed + +- (General) => Se vuelven a mostrar los parámetros en la url al aplicar un filtro + ## [2414.01] - 2024-04-04 ### Added diff --git a/cypress.config.js b/cypress.config.js index 1934f833e..e2046d6c4 100644 --- a/cypress.config.js +++ b/cypress.config.js @@ -3,6 +3,7 @@ const { defineConfig } = require('cypress'); module.exports = defineConfig({ e2e: { baseUrl: 'http://localhost:9000/', + experimentalStudio: true, fixturesFolder: 'test/cypress/fixtures', screenshotsFolder: 'test/cypress/screenshots', supportFile: 'test/cypress/support/index.js', diff --git a/package.json b/package.json index 82f21efe6..8398eb3f3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "salix-front", - "version": "24.16.0", + "version": "24.18.0", "description": "Salix frontend", "productName": "Salix", "author": "Verdnatura", @@ -32,6 +32,7 @@ "@intlify/unplugin-vue-i18n": "^0.8.1", "@pinia/testing": "^0.1.2", "@quasar/app-vite": "^1.7.3", + "@quasar/quasar-app-extension-qcalendar": "4.0.0-beta.15", "@quasar/quasar-app-extension-testing-unit-vitest": "^0.4.0", "@vue/test-utils": "^2.4.4", "autoprefixer": "^10.4.14", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f3fe7df55..bdff559cc 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -49,6 +49,9 @@ devDependencies: '@quasar/app-vite': specifier: ^1.7.3 version: 1.7.3(eslint@8.56.0)(pinia@2.1.7)(quasar@2.14.5)(vue-router@4.2.5)(vue@3.4.19) + '@quasar/quasar-app-extension-qcalendar': + specifier: 4.0.0-beta.15 + version: 4.0.0-beta.15 '@quasar/quasar-app-extension-testing-unit-vitest': specifier: ^0.4.0 version: 0.4.0(@vue/test-utils@2.4.4)(quasar@2.14.5)(vite@5.1.4)(vitest@0.31.4)(vue@3.4.19) @@ -912,6 +915,13 @@ packages: resolution: {integrity: sha512-SlOhwzXyPQHWgQIS2ncyDdYdksCJvUYNtgsDQqzAKEG3r3d/ejOxvThle79HTK3Q6HB+gQWFG21Ux00Osr5XSw==} dev: false + /@quasar/quasar-app-extension-qcalendar@4.0.0-beta.15: + resolution: {integrity: sha512-i6hQkcP70LXLfVMPZMKQjSg3681gjZmASV3vq6ULzc0LhtBiPneLdVNNtH2itkWxAmaUj+1heQDI5Pa0F7VKLQ==} + engines: {node: '>= 10.0.0', npm: '>= 5.6.0', yarn: '>= 1.6.0'} + dependencies: + '@quasar/quasar-ui-qcalendar': 4.0.0-beta.19 + dev: true + /@quasar/quasar-app-extension-testing-unit-vitest@0.4.0(@vue/test-utils@2.4.4)(quasar@2.14.5)(vite@5.1.4)(vitest@0.31.4)(vue@3.4.19): resolution: {integrity: sha512-eyzdUdmZiCueNS+5nedjMmzdbpCetSrtdGIwW6KplW1dTzRbLiNvYUjpBOxQGmJCgEhWy9zuswJ7MZ/bTql24Q==} engines: {node: '>= 12.22.1', npm: '>= 6.14.12', yarn: '>= 1.17.3'} @@ -939,6 +949,10 @@ packages: - vite dev: true + /@quasar/quasar-ui-qcalendar@4.0.0-beta.19: + resolution: {integrity: sha512-BT0G2JjgKl1bqNrY5utcYeoy8gK+U9k3Pz1YDi1OB265W/jHU6nFoWMEUdY3JdvMccwkXTL2DLVyl3eqAUyLyg==} + dev: true + /@quasar/render-ssr-error@1.0.3: resolution: {integrity: sha512-A8RF99q6/sOSe1Ighnh5syEIbliD3qUYEJd2HyfFyBPSMF+WYGXon5dmzg4nUoK662NgOggInevkDyBDJcZugg==} engines: {node: '>= 16'} diff --git a/quasar.config.js b/quasar.config.js index 5ce46667c..dd7a91002 100644 --- a/quasar.config.js +++ b/quasar.config.js @@ -93,13 +93,11 @@ module.exports = configure(function (/* ctx */) { [ VueI18nPlugin({ runtimeOnly: false, + include: [ + path.resolve(__dirname, './src/i18n/locale/**'), + path.resolve(__dirname, './src/pages/**/locale/**'), + ], }), - { - // if you want to use Vue I18n Legacy API, you need to set `compositionOnly: false` - // compositionOnly: false, - // you need to set i18n resource including paths ! - include: path.resolve(__dirname, './src/i18n/**'), - }, ], ], }, diff --git a/quasar.extensions.json b/quasar.extensions.json index e5c5cbfaa..867769090 100644 --- a/quasar.extensions.json +++ b/quasar.extensions.json @@ -1,7 +1,6 @@ { - "@quasar/testing-unit-vitest": { - "options": [ - "scripts" - ] - } -} \ No newline at end of file + "@quasar/testing-unit-vitest": { + "options": ["scripts"] + }, + "@quasar/qcalendar": {} +} diff --git a/src/App.vue b/src/App.vue index d0d8c9358..27cc34c38 100644 --- a/src/App.vue +++ b/src/App.vue @@ -16,7 +16,7 @@ onMounted(() => { if (availableLocales.includes(userLang)) { locale.value = userLang; } else { - locale.value = fallbackLocale; + locale.value = fallbackLocale.value; } }); diff --git a/src/components/CreateNewPostcodeForm.vue b/src/components/CreateNewPostcodeForm.vue index 47836c05b..02e84849c 100644 --- a/src/components/CreateNewPostcodeForm.vue +++ b/src/components/CreateNewPostcodeForm.vue @@ -28,8 +28,23 @@ const countriesOptions = ref([]); const provincesOptions = ref([]); const townsLocationOptions = ref([]); -const onDataSaved = (dataSaved) => { - emit('onDataSaved', dataSaved); +const onDataSaved = (formData) => { + const newPostcode = { + ...formData + }; + const townObject = townsLocationOptions.value.find( + ({id}) => id === formData.townFk + ); + newPostcode.town = townObject?.name; + const provinceObject = provincesOptions.value.find( + ({id}) => id === formData.provinceFk + ); + newPostcode.province = provinceObject?.name; + const countryObject = countriesOptions.value.find( + ({id}) => id === formData.countryFk + ); + newPostcode.country = countryObject?.country; + emit('onDataSaved', newPostcode); }; const onCityCreated = async ({ name, provinceFk }, formData) => { @@ -73,7 +88,7 @@ const onProvinceCreated = async ({ name }, formData) => { :title="t('New postcode')" :subtitle="t('Please, ensure you put the correct data!')" :form-initial-data="postcodeFormData" - @on-data-saved="onDataSaved($event)" + @on-data-saved="onDataSaved" > diff --git a/src/components/ui/VnPaginate.vue b/src/components/ui/VnPaginate.vue index d1b2f5ccb..b259bf8be 100644 --- a/src/components/ui/VnPaginate.vue +++ b/src/components/ui/VnPaginate.vue @@ -61,7 +61,6 @@ const props = defineProps({ }); const emit = defineEmits(['onFetch', 'onPaginate']); -defineExpose({ fetch }); const isLoading = ref(false); const pagination = ref({ sortBy: props.order, @@ -78,6 +77,7 @@ const arrayData = useArrayData(props.dataKey, { userParams: props.userParams, exprBuilder: props.exprBuilder, }); +const hasMoreData = ref(); const store = arrayData.store; onMounted(() => { @@ -91,6 +91,10 @@ watch( } ); +const addFilter = async (filter, params) => { + await arrayData.addFilter({ filter, params }); +}; + async function fetch() { await arrayData.fetch({ append: false }); if (!arrayData.hasMoreData.value) { @@ -106,11 +110,10 @@ async function paginate() { isLoading.value = true; await arrayData.loadMore(); - if (!arrayData.hasMoreData.value) { if (store.userParamsChanged) arrayData.hasMoreData.value = true; store.userParamsChanged = false; - isLoading.value = false; + endPagination(); return; } @@ -120,12 +123,15 @@ async function paginate() { pagination.value.sortBy = sortBy; pagination.value.descending = descending; - isLoading.value = false; + endPagination(); +} +function endPagination() { + hasMoreData.value = arrayData.hasMoreData.value; + isLoading.value = false; emit('onFetch', store.data); emit('onPaginate'); } - async function onLoad(index, done) { if (!store.data) { return done(); @@ -140,6 +146,8 @@ async function onLoad(index, done) { if (store.userParamsChanged) isDone = !arrayData.hasMoreData.value; done(isDone); } + +defineExpose({ fetch, addFilter }); es: diff --git a/src/pages/InvoiceIn/InvoiceInFilter.vue b/src/pages/InvoiceIn/InvoiceInFilter.vue index 8f8213f1c..0e53fbed7 100644 --- a/src/pages/InvoiceIn/InvoiceInFilter.vue +++ b/src/pages/InvoiceIn/InvoiceInFilter.vue @@ -29,6 +29,7 @@ const suppliersRef = ref(); order="nickname" limit="30" @on-fetch="(data) => (suppliers = data)" + auto-load /> diff --git a/src/pages/Item/ItemCreate.vue b/src/pages/Item/ItemCreate.vue new file mode 100644 index 000000000..18e7522cb --- /dev/null +++ b/src/pages/Item/ItemCreate.vue @@ -0,0 +1,170 @@ + + + diff --git a/src/pages/Item/ItemList.vue b/src/pages/Item/ItemList.vue index 49a5dbb64..3e399e29f 100644 --- a/src/pages/Item/ItemList.vue +++ b/src/pages/Item/ItemList.vue @@ -1 +1,577 @@ - + + + + + +es: + New item: Nuevo artículo + All it's properties will be copied: Todas sus propiedades serán copiadas + Do you want to clone this item?: ¿Desea clonar este artículo? + Clone: Clonar + Preview: Vista previa + diff --git a/src/pages/Login/LoginMain.vue b/src/pages/Login/LoginMain.vue index f920854c6..fcde51edf 100644 --- a/src/pages/Login/LoginMain.vue +++ b/src/pages/Login/LoginMain.vue @@ -55,7 +55,7 @@ async function onSubmit() { if (res.response?.data?.error?.code === 'REQUIRES_2FA') { Notify.create({ message: t('login.twoFactorRequired'), - icon: 'phonelink_lock', + icon: 'phoneLink_lock', type: 'warning', }); params.keepLogin = keepLogin.value; diff --git a/src/pages/Order/Card/OrderDescriptor.vue b/src/pages/Order/Card/OrderDescriptor.vue index 1c770194a..60e86d04e 100644 --- a/src/pages/Order/Card/OrderDescriptor.vue +++ b/src/pages/Order/Card/OrderDescriptor.vue @@ -61,7 +61,7 @@ const data = ref(useCardDescription()); const setData = (entity) => { if (!entity) return; data.value = useCardDescription(entity.client.name, entity.id); - state.set('ClaimDescriptor', entity); + state.set('OrderDescriptor', entity); }; const getConfirmationValue = (isConfirmed) => { diff --git a/src/pages/Route/RouteRoadmap.vue b/src/pages/Route/RouteRoadmap.vue index b1d5d4159..4053b57c7 100644 --- a/src/pages/Route/RouteRoadmap.vue +++ b/src/pages/Route/RouteRoadmap.vue @@ -277,7 +277,6 @@ function navigateToRoadmapSummary(event, row) { .route-list { width: 100%; } - .table-actions { gap: 12px; } diff --git a/src/pages/Ticket/Card/TicketSummary.vue b/src/pages/Ticket/Card/TicketSummary.vue index 5d2b62944..bf818ef77 100644 --- a/src/pages/Ticket/Card/TicketSummary.vue +++ b/src/pages/Ticket/Card/TicketSummary.vue @@ -1,5 +1,5 @@ + + + + +es: + Name: Nombre + Last name: Apellidos + Business phone: Teléfono de empresa + Mobile extension: Extensión móvil + Personal phone: Teléfono personal + Boss: Jefe + Marital status: Estado civil + Married: Casado/a + Single: Soltero/a + Origin country: País origen + Education level: Nivel educación + SSN: NSS + Locker: Taquilla + diff --git a/src/pages/Worker/Card/WorkerCalendar.vue b/src/pages/Worker/Card/WorkerCalendar.vue new file mode 100644 index 000000000..288e78dcf --- /dev/null +++ b/src/pages/Worker/Card/WorkerCalendar.vue @@ -0,0 +1,239 @@ + + + + + + + +en: + addAbsencesText: To start adding absences, click an absence type from the right menu and then on the day you want to add an absence + +es: + Search worker: Buscar trabajador + You can search by worker id or name: Puedes buscar por id o nombre del trabajador + addAbsencesText: Para empezar a añadir ausencias, haz clic en un tipo de ausencia desde el menu de la derecha y después en el día que quieres añadir la ausencia + diff --git a/src/pages/Worker/Card/WorkerCalendarFilter.vue b/src/pages/Worker/Card/WorkerCalendarFilter.vue new file mode 100644 index 000000000..374762ac1 --- /dev/null +++ b/src/pages/Worker/Card/WorkerCalendarFilter.vue @@ -0,0 +1,248 @@ + + + + + + + +en: + spentHours: Spent {hoursEnjoyed} of {totalHours} hours + usedDays: Used {holidaysEnjoyed} of {totalHolidays} days + paidHolidays: Paid holidays {payedHolidays} days + +es: + Paid holidays: Vacaciones pagadas + Year: Año + Contract: Contrato + Festive: Festivo + Current day: Día actual + spentHours: Utilizadas {hoursEnjoyed} de {totalHours} horas + usedDays: Utilizados {holidaysEnjoyed} de {totalHolidays} días + paidHolidays: Vacaciones pagadas {payedHolidays} días + + diff --git a/src/pages/Worker/Card/WorkerCalendarItem.vue b/src/pages/Worker/Card/WorkerCalendarItem.vue new file mode 100644 index 000000000..584222d19 --- /dev/null +++ b/src/pages/Worker/Card/WorkerCalendarItem.vue @@ -0,0 +1,313 @@ + + + + + + + +es: + Choose an absence type from the right menu: Elige un tipo de ausencia desde el menú de la derecha + diff --git a/src/pages/Worker/Card/WorkerDescriptor.vue b/src/pages/Worker/Card/WorkerDescriptor.vue index 5144b3bfa..bb4acec69 100644 --- a/src/pages/Worker/Card/WorkerDescriptor.vue +++ b/src/pages/Worker/Card/WorkerDescriptor.vue @@ -1,5 +1,5 @@ + diff --git a/src/pages/Worker/Card/WorkerEventLabel.vue b/src/pages/Worker/Card/WorkerEventLabel.vue new file mode 100644 index 000000000..b75fea890 --- /dev/null +++ b/src/pages/Worker/Card/WorkerEventLabel.vue @@ -0,0 +1,33 @@ + + + diff --git a/src/pages/Worker/Card/WorkerNotes.vue b/src/pages/Worker/Card/WorkerNotes.vue new file mode 100644 index 000000000..6c74aefa0 --- /dev/null +++ b/src/pages/Worker/Card/WorkerNotes.vue @@ -0,0 +1,38 @@ + + + diff --git a/src/pages/Worker/Card/WorkerPBX.vue b/src/pages/Worker/Card/WorkerPBX.vue new file mode 100644 index 000000000..681194061 --- /dev/null +++ b/src/pages/Worker/Card/WorkerPBX.vue @@ -0,0 +1,70 @@ + + + diff --git a/src/pages/Worker/Card/WorkerSummary.vue b/src/pages/Worker/Card/WorkerSummary.vue index dad21cda5..43c493565 100644 --- a/src/pages/Worker/Card/WorkerSummary.vue +++ b/src/pages/Worker/Card/WorkerSummary.vue @@ -10,7 +10,7 @@ import CardSummary from 'components/ui/CardSummary.vue'; import VnUserLink from 'src/components/ui/VnUserLink.vue'; import VnTitle from 'src/components/common/VnTitle.vue'; -const route = useRoute(); +const { params } = useRoute(); const { t } = useI18n(); const $props = defineProps({ @@ -20,53 +20,18 @@ const $props = defineProps({ }, }); -const entityId = computed(() => $props.id || route.params.id); +const entityId = computed(() => $props.id || params.id); const workerUrl = ref(); onMounted(async () => { workerUrl.value = (await getUrl('')) + `worker/${entityId.value}/`; }); -const filter = { - include: [ - { - relation: 'user', - scope: { - fields: ['email', 'name', 'nickname', 'roleFk'], - include: { - relation: 'role', - scope: { - fields: ['name'], - }, - }, - }, - }, - { - relation: 'department', - scope: { - include: { - relation: 'department', - scope: { - fields: ['name'], - }, - }, - }, - }, - { - relation: 'boss', - }, - { - relation: 'client', - }, - { - relation: 'sip', - }, - ], -}; +const filter = { where: { id: entityId.value } }; - - - diff --git a/src/router/modules/Supplier.js b/src/router/modules/Supplier.js index 64c48146b..da45aad2f 100644 --- a/src/router/modules/Supplier.js +++ b/src/router/modules/Supplier.js @@ -45,7 +45,8 @@ export default { path: 'create', name: 'SupplierCreate', meta: { - title: 'create', + title: 'supplierCreate', + icon: 'add', }, component: () => import('src/pages/Supplier/SupplierCreate.vue'), }, diff --git a/src/router/modules/customer.js b/src/router/modules/customer.js index 75188bd32..76d9a5af1 100644 --- a/src/router/modules/customer.js +++ b/src/router/modules/customer.js @@ -55,7 +55,8 @@ export default { path: 'create', name: 'CustomerCreate', meta: { - title: 'create', + title: 'customerCreate', + icon: 'add', }, component: () => import('src/pages/Customer/CustomerCreate.vue'), }, diff --git a/src/router/modules/entry.js b/src/router/modules/entry.js index 50a651af5..67fc41824 100644 --- a/src/router/modules/entry.js +++ b/src/router/modules/entry.js @@ -34,7 +34,8 @@ export default { path: 'create', name: 'EntryCreate', meta: { - title: 'create', + title: 'entryCreate', + icon: 'add', }, component: () => import('src/pages/Entry/EntryCreate.vue'), }, diff --git a/src/router/modules/item.js b/src/router/modules/item.js index d3462e15c..3dc8a1e6b 100644 --- a/src/router/modules/item.js +++ b/src/router/modules/item.js @@ -10,15 +10,15 @@ export default { component: RouterView, redirect: { name: 'ItemMain' }, menus: { - main: [], - card: [], + main: ['ItemList'], + card: ['ItemBasicData'], }, children: [ { path: '', name: 'ItemMain', component: () => import('src/pages/Item/ItemMain.vue'), - redirect: { name: 'Itemlist' }, + redirect: { name: 'ItemList' }, children: [ { path: 'list', @@ -29,6 +29,14 @@ export default { }, component: () => import('src/pages/Item/ItemList.vue'), }, + { + path: 'create', + name: 'ItemCreate', + meta: { + title: 'create', + }, + component: () => import('src/pages/Item/ItemCreate.vue'), + }, ], }, { @@ -64,6 +72,15 @@ export default { }, component: () => import('src/pages/Item/Card/ItemTags.vue'), }, + { + path: 'basic-data', + name: 'ItemBasicData', + meta: { + title: 'basicData', + icon: 'vn:settings', + }, + component: () => import('src/pages/Item/Card/ItemBasicData.vue'), + }, ], }, ], diff --git a/src/router/modules/order.js b/src/router/modules/order.js index 16d73281b..eb5424e75 100644 --- a/src/router/modules/order.js +++ b/src/router/modules/order.js @@ -34,7 +34,8 @@ export default { path: 'create', name: 'OrderCreate', meta: { - title: 'create', + title: 'orderCreate', + icon: 'add', }, component: () => import('src/pages/Order/Card/OrderForm.vue'), }, diff --git a/src/router/modules/route.js b/src/router/modules/route.js index 099492981..f8ededf55 100644 --- a/src/router/modules/route.js +++ b/src/router/modules/route.js @@ -34,7 +34,8 @@ export default { path: 'create', name: 'RouteCreate', meta: { - title: 'create', + title: 'routeCreate', + icon: 'add', }, component: () => import('src/pages/Route/Card/RouteForm.vue'), }, diff --git a/src/router/modules/shelving.js b/src/router/modules/shelving.js index b881ca020..d20ce40f4 100644 --- a/src/router/modules/shelving.js +++ b/src/router/modules/shelving.js @@ -34,7 +34,8 @@ export default { path: 'create', name: 'ShelvingCreate', meta: { - title: 'create', + title: 'shelvingCreate', + icon: 'add', }, component: () => import('src/pages/Shelving/Card/ShelvingForm.vue'), }, diff --git a/src/router/modules/travel.js b/src/router/modules/travel.js index 2f1e2150e..e1a08e9de 100644 --- a/src/router/modules/travel.js +++ b/src/router/modules/travel.js @@ -44,6 +44,7 @@ export default { name: 'TravelCreate', meta: { title: 'travelCreate', + icon: 'add', }, component: () => import('src/pages/Travel/TravelCreate.vue'), }, diff --git a/src/router/modules/worker.js b/src/router/modules/worker.js index 448aab79c..bf8d6093f 100644 --- a/src/router/modules/worker.js +++ b/src/router/modules/worker.js @@ -12,7 +12,16 @@ export default { redirect: { name: 'WorkerMain' }, menus: { main: ['WorkerList', 'WorkerDepartment'], - card: ['WorkerNotificationsManager', 'WorkerPda', 'WorkerLog'], + card: [ + 'WorkerBasicData', + 'WorkerNotes', + 'WorkerPda', + 'WorkerNotificationsManager', + 'WorkerPBX', + 'WorkerLog', + 'WorkerCalendar', + 'WorkerDms', + ], departmentCard: ['BasicData'], }, children: [ @@ -45,7 +54,7 @@ export default { name: 'WorkerCreate', meta: { title: 'workerCreate', - icon: '', + icon: 'add', }, component: () => import('src/pages/Worker/WorkerCreate.vue'), }, @@ -67,14 +76,30 @@ export default { component: () => import('src/pages/Worker/Card/WorkerSummary.vue'), }, { - name: 'WorkerNotificationsManager', - path: 'notifications', + path: 'basic-data', + name: 'WorkerBasicData', meta: { - title: 'notifications', - icon: 'notifications', + title: 'basicData', + icon: 'vn:settings', }, - component: () => - import('src/pages/Worker/Card/WorkerNotificationsManager.vue'), + component: () => import('src/pages/Worker/Card/WorkerBasicData.vue'), + }, + { + path: 'notes', + name: 'NotesCard', + redirect: { name: 'WorkerNotes' }, + children: [ + { + path: '', + name: 'WorkerNotes', + meta: { + title: 'notes', + icon: 'vn:notes', + }, + component: () => + import('src/pages/Worker/Card/WorkerNotes.vue'), + }, + ], }, { name: 'WorkerPda', @@ -85,6 +110,34 @@ export default { }, component: () => import('src/pages/Worker/Card/WorkerPda.vue'), }, + { + name: 'WorkerNotificationsManager', + path: 'notifications', + meta: { + title: 'notifications', + icon: 'notifications', + }, + component: () => + import('src/pages/Worker/Card/WorkerNotificationsManager.vue'), + }, + { + path: 'pbx', + name: 'WorkerPBX', + meta: { + title: 'pbx', + icon: 'vn:pbx', + }, + component: () => import('src/pages/Worker/Card/WorkerPBX.vue'), + }, + { + name: 'WorkerDms', + path: 'dms', + meta: { + title: 'dms', + icon: 'cloud_upload', + }, + component: () => import('src/pages/Worker/Card/WorkerDms.vue'), + }, { name: 'WorkerLog', path: 'log', @@ -94,6 +147,15 @@ export default { }, component: () => import('src/pages/Worker/Card/WorkerLog.vue'), }, + { + name: 'WorkerCalendar', + path: 'calendar', + meta: { + title: 'calendar', + icon: 'calendar_today', + }, + component: () => import('src/pages/Worker/Card/WorkerCalendar.vue'), + }, ], }, ], diff --git a/src/stores/useNavigationStore.js b/src/stores/useNavigationStore.js index afd3af0c0..f075301f6 100644 --- a/src/stores/useNavigationStore.js +++ b/src/stores/useNavigationStore.js @@ -7,6 +7,7 @@ import routes from 'src/router/modules'; export const useNavigationStore = defineStore('navigationStore', () => { const modules = [ + 'item', 'shelving', 'order', 'customer', diff --git a/src/stores/useWeekdayStore.js b/src/stores/useWeekdayStore.js new file mode 100644 index 000000000..ad898c9a7 --- /dev/null +++ b/src/stores/useWeekdayStore.js @@ -0,0 +1,95 @@ +import { reactive, ref, computed } from 'vue'; +import { useI18n } from 'vue-i18n'; +import { defineStore } from 'pinia'; + +export const useWeekdayStore = defineStore('weekdayStore', () => { + const { t } = useI18n(); + + const weekdays = [ + { code: 'sun', name: 'Sunday' }, + { code: 'mon', name: 'Monday' }, + { code: 'tue', name: 'Tuesday' }, + { code: 'wed', name: 'Wednesday' }, + { code: 'thu', name: 'Thursday' }, + { code: 'fri', name: 'Friday' }, + { code: 'sat', name: 'Saturday' }, + ]; + + const monthCodes = [ + 'jan', + 'feb', + 'mar', + 'apr', + 'may', + 'jun', + 'jul', + 'aug', + 'sep', + 'oct', + 'nov', + 'dec', + ]; + + const localeOrder = { + es: ['mon', 'tue', 'wed', 'thu', 'fri', 'sat', 'sun'], + en: ['sun', 'mon', 'tue', 'wed', 'thu', 'fri', 'sat'], + }; + + const weekdaysMap = reactive({}); + const localeWeekdays = ref([]); + + const initStore = () => { + getWeekdaysMap(); + }; + + const getWeekdaysMap = () => { + if (Object.keys(weekdaysMap).length > 0) return weekdaysMap; + + weekdays.forEach((day, i) => { + const obj = { + ...day, + index: i, + char: day.name.substr(0, 1), + abr: day.name.substr(0, 3), + }; + weekdaysMap[day.code] = obj; + }); + }; + + const getLocales = computed(() => { + // El día de mañana esto permitirá ordenar los weekdays en base a el locale si se lo desea reemplazando localeOrder.es por localeOrder[locale] + const locales = []; + for (let code of localeOrder.es) { + const obj = { + ...weekdaysMap[code], + locale: t(`weekdays.${weekdaysMap[code].code}`), + localeChar: t(`weekdays.${weekdaysMap[code].code}`).substr(0, 1), + localeAbr: t(`weekdays.${weekdaysMap[code].code}`).substr(0, 3), + }; + locales.push(obj); + } + return locales; + }); + + const getLocaleMonths = computed(() => { + const locales = []; + for (let code of monthCodes) { + const obj = { + code: code, + locale: t(`months.${code}`), + }; + locales.push(obj); + } + return locales; + }); + + return { + initStore, + weekdaysMap, + localeWeekdays, + getLocales, + weekdays, + monthCodes, + getLocaleMonths, + }; +}); diff --git a/test/cypress/integration/VnLocation.spec.js b/test/cypress/integration/VnLocation.spec.js index 5892e3ad5..3a90afce9 100644 --- a/test/cypress/integration/VnLocation.spec.js +++ b/test/cypress/integration/VnLocation.spec.js @@ -8,41 +8,41 @@ describe('VnLocation', () => { cy.visit('/#/worker/create'); cy.waitForElement('.q-card'); }); - - it('Show all options', function() { - cy.get(inputLocation).click(); - cy.get(locationOptions).should('have.length',5); + it('Show all options', function() { + cy.get(inputLocation).click(); + cy.get(locationOptions).should('have.length.at.least',5); }); - - it('input filter location as "al"', function() { + it('input filter location as "al"', function() { cy.get(inputLocation).click(); cy.get(inputLocation).clear(); cy.get(inputLocation).type('al'); - cy.get(locationOptions).should('have.length',3); + cy.get(locationOptions).should('have.length.at.least',3); }); it('input filter location as "ecuador"', function() { cy.get(inputLocation).click(); cy.get(inputLocation).clear(); cy.get(inputLocation).type('ecuador'); - cy.get(locationOptions).should('have.length',1); + cy.get(locationOptions).should('have.length.at.least',1); cy.get(`${locationOptions}:nth-child(1)`).click(); cy.get(':nth-child(3) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(2) > .q-icon').click(); - }); }); describe('Fiscal-data',()=>{ - const inputLocation = ':nth-child(6) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control'; - beforeEach(() => { cy.viewport(1280, 720); cy.login('developer'); cy.visit('/#/supplier/567/fiscal-data', {timeout: 2000}); cy.waitForElement('.q-card'); }); - - it('Show locations options', function() { - cy.get(inputLocation).click(); - cy.get(locationOptions).should('have.length', 5); + it('Create postCode', function() { + cy.get(':nth-child(6) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(3) > .q-icon').click(); + cy.get(' .q-card > h1').should('have.text', 'New postcode'); + cy.get('.q-card > :nth-child(4) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(1) > input').clear('12'); + cy.get('.q-card > :nth-child(4) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control > :nth-child(1) > input').type('1234453'); + cy.selectOption('.q-dialog__inner > .column > #formModel > .q-card > :nth-child(4) > :nth-child(2) > .q-field > .q-field__inner > .q-field__control ', 'Valencia'); + cy.selectOption('.q-dialog__inner > .column > #formModel > .q-card > :nth-child(5) > :nth-child(1) > .q-field > .q-field__inner > .q-field__control ', 'Province one'); + cy.selectOption('.q-dialog__inner > .column > #formModel > .q-card > :nth-child(5) > :nth-child(2) > .q-field > .q-field__inner > .q-field__control ', 'España'); + cy.get('.q-mt-lg > .q-btn--standard').click(); }); }); }) diff --git a/test/cypress/integration/entry/entryDms.spec.js b/test/cypress/integration/entry/entryDms.spec.js index 79a9c5162..5f9fae3dd 100644 --- a/test/cypress/integration/entry/entryDms.spec.js +++ b/test/cypress/integration/entry/entryDms.spec.js @@ -5,37 +5,40 @@ describe('WagonTypeCreate', () => { cy.viewport(1920, 1080); cy.login('developer'); cy.visit(`/#/entry/${entryId}/dms`); - }); it('should create edit and remove new dms', () => { cy.addRow(); - cy.get('.icon-attach').click() + cy.get('.icon-attach').click(); cy.get('.q-file').selectFile('test/cypress/fixtures/image.jpg', { force: true, }); - cy.get("tbody > tr").then((value) => { + cy.get('tbody > tr').then((value) => { + const u = undefined; + //Create and check if exist new row let newFileTd = Cypress.$(value).length; cy.get('.q-btn--standard > .q-btn__content > .block').click(); expect(value).to.have.length(newFileTd++); - const newRowSelector = `tbody > :nth-child(${newFileTd})` + const newRowSelector = `tbody > :nth-child(${newFileTd})`; cy.waitForElement(newRowSelector); + cy.validateRow(newRowSelector, [u, u, u, u, 'ENTRADA ID 1']); //Edit new dms - const u = undefined; - cy.validateRow(newRowSelector, [u,u,u,u,'ENTRADA ID 1']) - cy.get(`tbody :nth-child(${newFileTd}) > .text-right > .flex > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`).click(); - }) - // cy.log('newFileTd', newFileTd) + const newDescription = 'entry id 1 modified'; + const textAreaSelector = + '.q-textarea > .q-field__inner > .q-field__control > .q-field__control-container'; + cy.get( + `tbody :nth-child(${newFileTd}) > .text-right > .no-wrap > :nth-child(2) > .q-btn > .q-btn__content > .q-icon` + ).click(); - // //Create and check if exist new row - // cy.log('newFileTd:', newFileTd); - // cy.get(`tbody :nth-child(${newFileTd}) > .text-right > .flex > :nth-child(2) > .q-btn > .q-btn__content > .q-icon`).click() + cy.get(textAreaSelector).clear(); + cy.get(textAreaSelector).type(newDescription); + cy.saveCard(); + cy.reload(); - // cy.get(`tbody :nth-child(${newFileTd}) > :nth-child(5) > .q-tr > :nth-child(1) > span`).then((value) => { - // cy.log(value) - // }); + cy.validateRow(newRowSelector, [u, u, u, u, newDescription]); + }); }); }); diff --git a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js index 811374b98..2f045f32c 100644 --- a/test/cypress/integration/invoiceIn/invoiceInVat.spec.js +++ b/test/cypress/integration/invoiceIn/invoiceInVat.spec.js @@ -37,6 +37,7 @@ describe('InvoiceInVat', () => { it('should throw an error if there are fields undefined', () => { cy.get(inputBtns).eq(0).click(); + cy.get(':nth-child(1) > .q-td.q-table--col-auto-width > .q-field > .q-field__inner > .q-field__control > :nth-child(2) > .default-icon').click(); cy.get(dialogBtns).eq(2).click(); cy.get('.q-notification__message').should('have.text', "The code can't be empty"); }); @@ -44,7 +45,7 @@ describe('InvoiceInVat', () => { it('should correctly handle expense addition', () => { cy.get(inputBtns).eq(0).click(); - cy.get(dialogInputs).eq(0).click(); + cy.get(':nth-child(1) > .q-td.q-table--col-auto-width > .q-field > .q-field__inner > .q-field__control > :nth-child(2) > .default-icon').click(); cy.get(dialogInputs).eq(0).type(randomInt); cy.get(dialogInputs).eq(1).click(); cy.get(dialogInputs).eq(1).type('This is a dummy expense'); diff --git a/test/cypress/integration/ticket/ticketDescriptor.spec.js b/test/cypress/integration/ticket/ticketDescriptor.spec.js index c212d3b4a..22401f0b4 100644 --- a/test/cypress/integration/ticket/ticketDescriptor.spec.js +++ b/test/cypress/integration/ticket/ticketDescriptor.spec.js @@ -1,7 +1,7 @@ /// describe('Ticket descriptor', () => { const toCloneOpt = '.q-list > :nth-child(5)'; - const warehouseValue = '.summaryBody > :nth-child(2) > :nth-child(6) > .value > span'; + const warehouseValue = ':nth-child(1) > :nth-child(6) > .value > span'; const summaryHeader = '.summaryHeader > div'; beforeEach(() => { diff --git a/test/cypress/integration/vnSearchBar.spec.js b/test/cypress/integration/vnSearchBar.spec.js index 3db789773..f1f3a9e82 100644 --- a/test/cypress/integration/vnSearchBar.spec.js +++ b/test/cypress/integration/vnSearchBar.spec.js @@ -36,7 +36,7 @@ describe('VnSearchBar', () => { const checkCardListAndUrl = (expectedLength) => { cy.get(cardList).then(($cardList) => { expect($cardList.find('.q-card').length).to.equal(expectedLength); - cy.url().then((currentUrl) => expect(currentUrl).to.equal(url)); + cy.url().then((currentUrl) => expect(currentUrl).to.contain(url)); }); }; }); diff --git a/test/cypress/integration/worker/workerList.spec.js b/test/cypress/integration/worker/workerList.spec.js index c950f9fed..38e7ea6d0 100644 --- a/test/cypress/integration/worker/workerList.spec.js +++ b/test/cypress/integration/worker/workerList.spec.js @@ -8,9 +8,9 @@ describe('WorkerList', () => { }); it('should load workers', () => { - cy.get(workerFieldNames).eq(0).should('have.text', 'JessicaJones'); - cy.get(workerFieldNames).eq(1).should('have.text', 'BruceBanner'); - cy.get(workerFieldNames).eq(2).should('have.text', 'CharlesXavier'); + cy.get(workerFieldNames).eq(0).should('have.text', 'jessicajones'); + cy.get(workerFieldNames).eq(1).should('have.text', 'brucebanner'); + cy.get(workerFieldNames).eq(2).should('have.text', 'charlesxavier'); }); it('should open the worker summary', () => { diff --git a/test/cypress/integration/worker/workerNotificationsManager.spec.js b/test/cypress/integration/worker/workerNotificationsManager.spec.js index 175933277..ac452c4ff 100644 --- a/test/cypress/integration/worker/workerNotificationsManager.spec.js +++ b/test/cypress/integration/worker/workerNotificationsManager.spec.js @@ -60,7 +60,6 @@ describe('WorkerNotificationsManager', () => { it('should active a notification if you are their boss', () => { cy.login('salesBoss'); cy.visit(`/#/worker/${salesPersonId}/notifications`); - cy.waitForElement(activeList); cy.waitForElement(availableList); cy.get(activeList) diff --git a/test/cypress/integration/worker/workerSummary.spec.js b/test/cypress/integration/worker/workerSummary.spec.js index 7228b4b31..3d70fdf96 100644 --- a/test/cypress/integration/worker/workerSummary.spec.js +++ b/test/cypress/integration/worker/workerSummary.spec.js @@ -6,7 +6,8 @@ describe('WorkerSummary', () => { }); it('should load worker summary', () => { - cy.get('.summaryHeader > div').should('have.text', '19 - salesBoss salesBoss'); + cy.waitForElement('.summaryHeader'); + cy.get('.summaryHeader > div').should('have.text', '19 - salesboss salesboss'); cy.get(':nth-child(1) > :nth-child(2) > .value > span').should( 'have.text', 'salesBossNick' diff --git a/test/vitest/__tests__/components/common/VnLog.spec.js b/test/vitest/__tests__/components/common/VnLog.spec.js index b654bff9b..53d2732a0 100644 --- a/test/vitest/__tests__/components/common/VnLog.spec.js +++ b/test/vitest/__tests__/components/common/VnLog.spec.js @@ -38,10 +38,10 @@ describe('VnLog', () => { action: 'update', changedModel: 'Claim', oldInstance: { - hasToPickUp: false, + pickup: null, }, newInstance: { - hasToPickUp: true, + pickup: 'agency', }, creationDate: '2023-09-18T12:25:34.000Z', changedModelId: '1', diff --git a/test/vitest/__tests__/composables/useArrayData.spec.js b/test/vitest/__tests__/composables/useArrayData.spec.js new file mode 100644 index 000000000..ae0ca7368 --- /dev/null +++ b/test/vitest/__tests__/composables/useArrayData.spec.js @@ -0,0 +1,31 @@ +import { describe, expect, it, beforeAll } from 'vitest'; +import { axios } from 'app/test/vitest/helper'; +import { useArrayData } from 'composables/useArrayData'; + +describe('useArrayData', () => { + let arrayData; + beforeAll(() => { + axios.get.mockResolvedValue({ data: [] }); + arrayData = useArrayData('InvoiceIn', { url: 'invoice-in/list' }); + Object.defineProperty(window.location, 'href', { + writable: true, + value: 'localhost:9000/invoice-in/list', + }); + + // Mock the window.history.pushState method within useArrayData + window.history.pushState = (data, title, url) => (window.location.href = url); + + // Mock the URL constructor within useArrayData + global.URL = class URL { + constructor(url) { + this.hash = url.split('localhost:9000/')[1]; + } + }; + }); + + it('should add the params to the url', async () => { + arrayData.store.userParams = { supplierFk: 2 }; + arrayData.updateStateParams(); + expect(window.location.href).contain('params=%7B%22supplierFk%22%3A2%7D'); + }); +}); diff --git a/vitest.config.js b/vitest.config.js index 5a8699e99..748bbfe0a 100644 --- a/vitest.config.js +++ b/vitest.config.js @@ -19,7 +19,7 @@ export default defineConfig({ plugins: [ vue({ template: { - transformAssetUrls + transformAssetUrls, }, }), quasar({