diff --git a/CHANGELOG.md b/CHANGELOG.md index 03812d252..e110e4cd6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,87 @@ +# Version 24.50 - 2024-12-10 + +### Added 🆕 + +- feat: add reportFileName option by:Javier Segarra +- feat: all clients just with global series by:jgallego +- feat: improve Merge branch 'test' into dev by:Javier Segarra +- feat: manual invoice in two lines by:jgallego +- feat: manualInvoice with address by:jgallego +- feat: randomize functions and example by:Javier Segarra +- feat: refs #6999 added search when user tabs on a filter with value by:Jon +- feat: refs #6999 added tab to search in VnTable filter by:Jon +- feat: refs #7346 #7346 improve form by:Javier Segarra +- feat: refs #7346 address ordered by:jgallego +- feat: refs #7346 radioButton by:jgallego +- feat: refs #7346 style radioButton by:jgallego +- feat: refs #7346 traducciones en cammelCase (7346-manualInvoice) by:jgallego +- feat: refs #8038 added new functionality in VnSelect and refactor styles by:Jon +- feat: refs #8061 #8061 updates by:Javier Segarra +- feat: refs #8087 reactive data by:jorgep +- feat: refs #8087 refs#8087 Redadas en travel by:Carlos Andrés +- feat: refs #8138 add component ticket problems by:pablone +- feat: refs #8163 add max length and more tests by:wbuezas +- feat: refs #8163 add prop by:wbuezas +- feat: refs #8163 add VnInput insert functionality and e2e test by:wbuezas +- feat: refs #8163 limit with maxLength by:Javier Segarra +- feat: refs #8163 maxLength SupplierFD account by:Javier Segarra +- feat: refs #8163 maxLengthVnInput by:Javier Segarra +- feat: refs #8163 use VnAccountNumber in VnAccountNumber by:Javier Segarra +- feat: refs #8166 show notification by:jorgep + +### Changed 📦 + +- feat: refs #8038 added new functionality in VnSelect and refactor styles by:Jon +- perf: add dataCy by:Javier Segarra +- perf: refs #7346 #7346 Imrpove interface dialog by:Javier Segarra +- perf: refs #7346 #7346 use v-show instead v-if by:Javier Segarra +- perf: refs #8036 currentFilter by:alexm +- perf: refs #8061 filter autonomy by:Javier Segarra +- perf: refs #8061 solve conflicts and random posCode it by:Javier Segarra +- perf: refs #8061 use opts from VnSelect by:Javier Segarra +- perf: refs #8163 #8061 createNewPostCodeForm by:Javier Segarra +- perf: remove console by:Javier Segarra +- perf: remove timeout by:Javier Segarra +- perf: test command fillInForm by:Javier Segarra +- refactor: refs #8162 remove comment by:wbuezas +- refactor: remove unnecesary things by:wbuezas + +### Fixed 🛠️ + +- fix: #8016 fetching data by:Javier Segarra +- fix: icons by:jgallego +- fix: refs #7229 download file by:jorgep +- fix: refs #7229 remove catch by:jorgep +- fix: refs #7229 set url by:jorgep +- fix: refs #7229 test by:jorgep +- fix: refs #7229 url by:jorgep +- fix: refs #7229 url + test by:jorgep +- fix: refs #7304 7304 clean warning by:carlossa +- fix: refs #7304 fix list by:carlossa +- fix: refs #7304 fix warning by:carlossa +- fix: refs #7346 traslations by:jgallego +- fix: refs #7529 add save by:carlossa +- fix: refs #7529 fix e2e by:carlossa +- fix: refs #7529 fix front by:carlossa +- fix: refs #7529 fix scss by:carlossa +- fix: refs #7529 fix te2e by:carlossa +- fix: refs #7529 fix workerPit e2e by:carlossa +- fix: refs #7529 front by:carlossa +- fix: refs #8036 apply exprBuilder after save filters by:alexm +- fix: refs #8036 only add where when required by:alexm +- fix: refs #8038 solve conflicts by:Jon +- fix: refs #8061 improve code dependencies (origin/8061_improve_newCP) by:Javier Segarra +- fix: refs #8138 move component from ui folder by:pablone +- fix: refs #8138 sme minor issues by:pablone +- fix: refs #8163 #8061 createNewPostCodeForm by:Javier Segarra +- fix: refs #8163 minor problem when keypress by:Javier Segarra +- fix: refs #8166 show zone error by:jorgep +- fix: removed selectedClient by:jgallego +- refs #7529 fix workerPit by:carlossa +- revert: refs #8061 test #8061 updates by:Javier Segarra +- test: fix own test by:Javier Segarra +- test: refs #8162 #8162 fix TicketList spec by:Javier Segarra + # Version 24.48 - 2024-11-25 ### Added 🆕 diff --git a/src/boot/quasar.js b/src/boot/quasar.js index d375c2f69..547517682 100644 --- a/src/boot/quasar.js +++ b/src/boot/quasar.js @@ -1,20 +1,18 @@ +import axios from 'axios'; import { boot } from 'quasar/wrappers'; import qFormMixin from './qformMixin'; import keyShortcut from './keyShortcut'; -import useNotify from 'src/composables/useNotify.js'; -import { CanceledError } from 'axios'; import { QForm } from 'quasar'; import { QLayout } from 'quasar'; import mainShortcutMixin from './mainShortcutMixin'; - -const { notify } = useNotify(); +import { useCau } from 'src/composables/useCau'; export default boot(({ app }) => { QForm.mixins = [qFormMixin]; QLayout.mixins = [mainShortcutMixin]; app.directive('shortcut', keyShortcut); - app.config.errorHandler = (error) => { + app.config.errorHandler = async (error) => { let message; const response = error.response; const responseData = response?.data; @@ -45,12 +43,12 @@ export default boot(({ app }) => { } console.error(error); - if (error instanceof CanceledError) { + if (error instanceof axios.CanceledError) { const env = process.env.NODE_ENV; if (env && env !== 'development') return; message = 'Duplicate request'; } - notify(message ?? 'globals.error', 'negative', 'error'); + await useCau(response, message); }; }); diff --git a/src/components/CreateNewPostcodeForm.vue b/src/components/CreateNewPostcodeForm.vue index d3d6708f0..c656fcb2f 100644 --- a/src/components/CreateNewPostcodeForm.vue +++ b/src/components/CreateNewPostcodeForm.vue @@ -25,7 +25,6 @@ const townsFetchDataRef = ref(false); const townFilter = ref({}); const countriesRef = ref(false); -const provincesFetchDataRef = ref(false); const provincesOptions = ref([]); const townsOptions = ref([]); const town = ref({}); @@ -71,9 +70,6 @@ async function setProvince(id, data) { await fetchTowns(); } async function onProvinceCreated(data) { - await provincesFetchDataRef.value.fetch({ - where: { countryFk: postcodeFormData.countryFk }, - }); postcodeFormData.provinceFk = data.id; } function provinceByCountry(countryFk = postcodeFormData.countryFk) { @@ -92,7 +88,6 @@ function setTown(newTown, data) { data.countryFk = newTown?.province?.countryFk ?? newTown; } async function onCityCreated(newTown, formData) { - await provincesFetchDataRef.value.fetch(); newTown.province = provincesOptions.value.find( (province) => province.id === newTown.provinceFk ); @@ -125,14 +120,6 @@ async function filterTowns(name) { - setProvince(value, data)" + @update:options=" + (data) => { + provincesOptions = data; + } + " v-model="data.provinceFk" @on-province-created="onProvinceCreated" required diff --git a/src/components/VnSelectProvince.vue b/src/components/VnSelectProvince.vue index 7d1297abf..d73ee964e 100644 --- a/src/components/VnSelectProvince.vue +++ b/src/components/VnSelectProvince.vue @@ -7,7 +7,7 @@ import VnSelectDialog from 'components/common/VnSelectDialog.vue'; import FetchData from 'components/FetchData.vue'; import CreateNewProvinceForm from './CreateNewProvinceForm.vue'; -const emit = defineEmits(['onProvinceCreated', 'onProvinceFetched']); +const emit = defineEmits(['onProvinceCreated', 'onProvinceFetched', 'update:options']); const $props = defineProps({ countryFk: { type: Number, @@ -41,6 +41,7 @@ async function onProvinceCreated(_, data) { } async function handleProvinces(data) { provincesOptions.value = data; + emit('update:options', data); } watch( diff --git a/src/components/common/VnSelect.vue b/src/components/common/VnSelect.vue index e116be32a..e5ac05231 100644 --- a/src/components/common/VnSelect.vue +++ b/src/components/common/VnSelect.vue @@ -268,7 +268,7 @@ async function onScroll({ to, direction, from, index }) { defineExpose({ opts: myOptions }); function handleKeyDown(event) { - if (event.key === 'Tab') { + if (event.key === 'Tab' && !event.shiftKey) { event.preventDefault(); const inputValue = vnSelectRef.value?.inputValue; @@ -286,6 +286,17 @@ function handleKeyDown(event) { } vnSelectRef.value?.hidePopup(); } + + const focusableElements = document.querySelectorAll( + 'a, button, input, textarea, select, details, [tabindex]:not([tabindex="-1"])' + ); + const currentIndex = Array.prototype.indexOf.call( + focusableElements, + event.target + ); + if (currentIndex >= 0 && currentIndex < focusableElements.length - 1) { + focusableElements[currentIndex + 1].focus(); + } } } diff --git a/src/composables/useCau.js b/src/composables/useCau.js new file mode 100644 index 000000000..29319bd9a --- /dev/null +++ b/src/composables/useCau.js @@ -0,0 +1,73 @@ +import VnInput from 'src/components/common/VnInput.vue'; +import { useVnConfirm } from 'src/composables/useVnConfirm'; +import axios from 'axios'; +import { ref } from 'vue'; +import { i18n } from 'src/boot/i18n'; +import useNotify from 'src/composables/useNotify.js'; + +export async function useCau(res, message) { + const { notify } = useNotify(); + const { openConfirmationModal } = useVnConfirm(); + const { config, headers, request, status, statusText, data } = res || {}; + const { params, url, method, signal, headers: confHeaders } = config || {}; + const { message: resMessage, code, name } = data?.error || {}; + + const additionalData = { + path: location.hash, + message: resMessage, + code, + request: request?.responseURL, + status, + name, + statusText: statusText, + config: { + url, + method, + params, + headers: confHeaders, + aborted: signal?.aborted, + version: headers?.['salix-version'], + }, + }; + const opts = { + actions: [ + { + icon: 'support_agent', + color: 'primary', + dense: true, + flat: false, + round: true, + handler: async () => { + const locale = i18n.global.t; + const reason = ref( + code == 'ACCESS_DENIED' ? locale('cau.askPrivileges') : '' + ); + openConfirmationModal( + locale('cau.title'), + locale('cau.subtitle'), + async () => { + await axios.post('OsTickets/send-to-support', { + reason: reason.value, + additionalData, + }); + }, + null, + { + component: VnInput, + props: { + modelValue: reason, + 'onUpdate:modelValue': (val) => (reason.value = val), + label: locale('cau.inputLabel'), + class: 'full-width', + required: true, + autofocus: true, + }, + } + ); + }, + }, + ], + }; + + notify(message ?? 'globals.error', 'negative', 'error', opts); +} diff --git a/src/composables/useNotify.js b/src/composables/useNotify.js index 2f0e1c257..309156d2a 100644 --- a/src/composables/useNotify.js +++ b/src/composables/useNotify.js @@ -2,7 +2,7 @@ import { Notify } from 'quasar'; import { i18n } from 'src/boot/i18n'; export default function useNotify() { - const notify = (message, type, icon) => { + const notify = (message, type, icon, opts = {}) => { const defaultIcons = { warning: 'warning', negative: 'error', @@ -13,6 +13,7 @@ export default function useNotify() { message: i18n.global.t(message), type: type, icon: icon ? icon : defaultIcons[type], + ...opts, }); }; diff --git a/src/composables/useVnConfirm.js b/src/composables/useVnConfirm.js index 76c3f4f28..4438ad11d 100644 --- a/src/composables/useVnConfirm.js +++ b/src/composables/useVnConfirm.js @@ -1,22 +1,29 @@ +import { h } from 'vue'; +import { Dialog } from 'quasar'; import VnConfirm from 'components/ui/VnConfirm.vue'; -import { useQuasar } from 'quasar'; export function useVnConfirm() { - const quasar = useQuasar(); - - const openConfirmationModal = (title, message, promise, successFn) => { - quasar - .dialog({ - component: VnConfirm, - componentProps: { + const openConfirmationModal = ( + title, + message, + promise, + successFn, + customHTML = {} + ) => { + const { component, props } = customHTML; + Dialog.create({ + component: h( + VnConfirm, + { title: title, message: message, promise: promise, }, - }) - .onOk(async () => { - if (successFn) successFn(); - }); + { customHTML: () => h(component, props) } + ), + }).onOk(async () => { + if (successFn) successFn(); + }); }; return { openConfirmationModal }; diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index d12fc7230..c9f590565 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -369,6 +369,11 @@ resetPassword: repeatPassword: Repeat password passwordNotMatch: Passwords don't match passwordChanged: Password changed +cau: + title: Send cau + subtitle: By sending this ticket, all the data related to the error, the section, the user, etc., are already sent. + inputLabel: Explain why this error should not appear + askPrivileges: Ask for privileges entry: list: newEntry: New entry diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml index 365abd824..61a5984cb 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -371,6 +371,11 @@ resetPassword: repeatPassword: Repetir contraseña passwordNotMatch: Las contraseñas no coinciden passwordChanged: Contraseña cambiada +cau: + title: Enviar cau + subtitle: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc + inputLabel: Explique el motivo por el que no deberia aparecer este fallo + askPrivileges: Solicitar permisos entry: list: newEntry: Nueva entrada diff --git a/src/pages/Account/Card/AccountDescriptorMenu.vue b/src/pages/Account/Card/AccountDescriptorMenu.vue index 6f1d2ca1f..1780b4247 100644 --- a/src/pages/Account/Card/AccountDescriptorMenu.vue +++ b/src/pages/Account/Card/AccountDescriptorMenu.vue @@ -8,7 +8,7 @@ import { useAcl } from 'src/composables/useAcl'; import { useArrayData } from 'src/composables/useArrayData'; import VnConfirm from 'src/components/ui/VnConfirm.vue'; import VnChangePassword from 'src/components/common/VnChangePassword.vue'; -import useNotify from 'src/composables/useNotify.js'; +import { useQuasar } from 'quasar'; const $props = defineProps({ hasAccount: { @@ -21,7 +21,7 @@ const { t } = useI18n(); const { hasAccount } = toRefs($props); const { openConfirmationModal } = useVnConfirm(); const route = useRoute(); -const { notify } = useNotify(); +const { notify } = useQuasar(); const account = computed(() => useArrayData('AccountId').store.data[0]); account.value.hasAccount = hasAccount.value; const entityId = computed(() => +route.params.id); diff --git a/src/pages/Customer/Card/CustomerSummary.vue b/src/pages/Customer/Card/CustomerSummary.vue index f4c5e6e09..ae4c7f3ab 100644 --- a/src/pages/Customer/Card/CustomerSummary.vue +++ b/src/pages/Customer/Card/CustomerSummary.vue @@ -101,7 +101,7 @@ const sumRisk = ({ clientRisks }) => { {{ t('globals.params.email') }} - { +const cloneRoutes = async () => { if (!selectedRows.value.length || !startingDate.value) return; - axios.post('Routes/clone', { - created: startingDate.value, + await axios.post('Routes/clone', { + dated: startingDate.value, ids: selectedRows.value.map((row) => row?.id), }); startingDate.value = null; @@ -274,7 +274,6 @@ const openTicketsDialog = (id) => { {{ t('route.Select the starting date') }} -
{{ t('route.Select the starting date') }}