From 8817fd7c5582934a91b2ec9d852c46e0517122a5 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 30 Oct 2024 13:55:51 +0100 Subject: [PATCH 01/13] feat: add support service wip --- src/boot/quasar.js | 58 ++++++++++++++++++++++++++++++-- src/components/NavBar.vue | 7 ++-- src/composables/useNotify.js | 3 +- src/composables/useVnConfirm.js | 31 ++++++++++------- src/i18n/locale/en.yml | 2 ++ src/i18n/locale/es.yml | 3 ++ src/stores/useStateQueryStore.js | 5 ++- 7 files changed, 90 insertions(+), 19 deletions(-) diff --git a/src/boot/quasar.js b/src/boot/quasar.js index 01fe68d8b..a1991d9a4 100644 --- a/src/boot/quasar.js +++ b/src/boot/quasar.js @@ -1,10 +1,17 @@ +import { ref } from 'vue'; +import axios from 'axios'; import { boot } from 'quasar/wrappers'; import qFormMixin from './qformMixin'; import keyShortcut from './keyShortcut'; +import { i18n } from './i18n'; import useNotify from 'src/composables/useNotify.js'; -import { CanceledError } from 'axios'; +import { useStateQueryStore } from 'src/stores/useStateQueryStore'; +import VnInput from 'src/components/common/VnInput.vue'; +import { useVnConfirm } from 'src/composables/useVnConfirm'; const { notify } = useNotify(); +const stateQuery = useStateQueryStore(); +const { openConfirmationModal } = useVnConfirm(); export default boot(({ app }) => { app.mixin(qFormMixin); @@ -40,12 +47,57 @@ 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'; } + // Convey to Alex or Juan... + const additionalData = { + frontPath: stateQuery.route.name, + backError: { + config: error.config, + data: error, + }, + httpRequest: error.request.response, + }; - notify(message ?? 'globals.error', 'negative', 'error'); + const opts = { + actions: [ + { + icon: 'support_agent', + color: 'primary', + dense: true, + flat: false, + round: true, + noDismiss: true, + handler: async () => { + const reason = ref(); + openConfirmationModal( + i18n.global.t('globals.sendCau'), + false, + 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: i18n.global.t('globals.ExplainReason'), + class: 'full-width', + required: true, + }, + } + ); + }, + }, + ], + }; + notify(message ?? 'globals.error', 'negative', 'error', opts); }; }); diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 9b0393489..6f8377d96 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -1,6 +1,7 @@ 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 10186d92a..7feaa990a 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -314,6 +314,8 @@ globals: deleteConfirmTitle: Delete selected elements changeState: Change state raid: 'Raid {daysInForward} days' + sendCau: Send cau + ExplainReason: Explain why this error should not appear errors: statusUnauthorized: Access denied statusInternalServerError: An internal server error has ocurred diff --git a/src/i18n/locale/es.yml b/src/i18n/locale/es.yml index 66b5efd52..be1e25ca8 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -318,6 +318,9 @@ globals: deleteConfirmTitle: Eliminar los elementos seleccionados changeState: Cambiar estado raid: 'Redada {daysInForward} días' + sendCau: Enviar cau + ExplainReason: Explique el motivo por el que no deberia aparecer este fallo + By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc errors: statusUnauthorized: Acceso denegado statusInternalServerError: Ha ocurrido un error interno del servidor diff --git a/src/stores/useStateQueryStore.js b/src/stores/useStateQueryStore.js index d25dbb921..9893d3264 100644 --- a/src/stores/useStateQueryStore.js +++ b/src/stores/useStateQueryStore.js @@ -3,7 +3,9 @@ import { defineStore } from 'pinia'; export const useStateQueryStore = defineStore('stateQueryStore', () => { const queries = ref(new Set()); - + const route = computed(() => + Array.from(queries.value).find((query) => query?.fullPath) + ); function add(query) { queries.value.add(query); return query; @@ -27,5 +29,6 @@ export const useStateQueryStore = defineStore('stateQueryStore', () => { remove, queries, reset, + route, }; }); From f6d200405ce236e88dcbc63152247b3d3a0766a2 Mon Sep 17 00:00:00 2001 From: jorgep Date: Tue, 5 Nov 2024 09:33:16 +0100 Subject: [PATCH 02/13] feat: message to grant access --- src/boot/quasar.js | 52 ++++++++++++++++++++++++++-------------------- 1 file changed, 30 insertions(+), 22 deletions(-) diff --git a/src/boot/quasar.js b/src/boot/quasar.js index a1991d9a4..b3fb62ee7 100644 --- a/src/boot/quasar.js +++ b/src/boot/quasar.js @@ -62,6 +62,8 @@ export default boot(({ app }) => { httpRequest: error.request.response, }; + const isErrorPrivaleges = response?.code == 'ACCESS_DENIED'; + const opts = { actions: [ { @@ -70,30 +72,36 @@ export default boot(({ app }) => { dense: true, flat: false, round: true, - noDismiss: true, + noDismiss: isErrorPrivaleges, handler: async () => { - const reason = ref(); - openConfirmationModal( - i18n.global.t('globals.sendCau'), - false, - 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: i18n.global.t('globals.ExplainReason'), - class: 'full-width', - required: true, + if (isErrorPrivaleges) { + // Create message and send to support + console.log('QUIERO ACCEDER!!!'); + } else { + const reason = ref(); + openConfirmationModal( + i18n.global.t('globals.sendCau'), + false, + 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: i18n.global.t('globals.ExplainReason'), + class: 'full-width', + required: true, + }, + } + ); + } }, }, ], From 0c476725ae5672cf3bef59d32255797e6e1d6116 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 13 Nov 2024 13:11:02 +0100 Subject: [PATCH 03/13] refactor: use locale keys --- src/boot/quasar.js | 56 +++++++++++++++++++----------------------- src/i18n/locale/en.yml | 7 ++++-- src/i18n/locale/es.yml | 8 +++--- 3 files changed, 35 insertions(+), 36 deletions(-) diff --git a/src/boot/quasar.js b/src/boot/quasar.js index b3fb62ee7..5e10bacf1 100644 --- a/src/boot/quasar.js +++ b/src/boot/quasar.js @@ -61,9 +61,6 @@ export default boot(({ app }) => { }, httpRequest: error.request.response, }; - - const isErrorPrivaleges = response?.code == 'ACCESS_DENIED'; - const opts = { actions: [ { @@ -72,36 +69,33 @@ export default boot(({ app }) => { dense: true, flat: false, round: true, - noDismiss: isErrorPrivaleges, handler: async () => { - if (isErrorPrivaleges) { - // Create message and send to support - console.log('QUIERO ACCEDER!!!'); - } else { - const reason = ref(); - openConfirmationModal( - i18n.global.t('globals.sendCau'), - false, - async () => { - await axios.post('OsTickets/send-to-support', { - reason: reason.value, - additionalData, - }); + const reason = ref( + response.data.error.code == 'ACCESS_DENIED' + ? i18n.global.t('cau.askPrivileges') + : '' + ); + openConfirmationModal( + i18n.global.t('cau.title'), + i18n.global.t('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: i18n.global.t('cau.inputLabel'), + class: 'full-width', + required: true, }, - null, - { - component: VnInput, - props: { - modelValue: reason, - 'onUpdate:modelValue': (val) => - (reason.value = val), - label: i18n.global.t('globals.ExplainReason'), - class: 'full-width', - required: true, - }, - } - ); - } + } + ); }, }, ], diff --git a/src/i18n/locale/en.yml b/src/i18n/locale/en.yml index e0d35d7e7..2eda4ddce 100644 --- a/src/i18n/locale/en.yml +++ b/src/i18n/locale/en.yml @@ -317,8 +317,6 @@ globals: deleteConfirmTitle: Delete selected elements changeState: Change state raid: 'Raid {daysInForward} days' - sendCau: Send cau - ExplainReason: Explain why this error should not appear errors: statusUnauthorized: Access denied statusInternalServerError: An internal server error has ocurred @@ -356,6 +354,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 ce8a8bf01..af475d27d 100644 --- a/src/i18n/locale/es.yml +++ b/src/i18n/locale/es.yml @@ -321,9 +321,6 @@ globals: deleteConfirmTitle: Eliminar los elementos seleccionados changeState: Cambiar estado raid: 'Redada {daysInForward} días' - sendCau: Enviar cau - ExplainReason: Explique el motivo por el que no deberia aparecer este fallo - By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.: Al enviar este cau ya se envían todos los datos relacionados con el error, la sección, el usuario, etc errors: statusUnauthorized: Acceso denegado statusInternalServerError: Ha ocurrido un error interno del servidor @@ -359,6 +356,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 From 34df9cf2543fe0eb2783966897bd2dfd77416020 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 13 Nov 2024 15:33:41 +0100 Subject: [PATCH 04/13] fix: rollback --- src/boot/quasar.js | 13 +++++++------ src/components/NavBar.vue | 7 ++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/src/boot/quasar.js b/src/boot/quasar.js index 5e10bacf1..103b4812e 100644 --- a/src/boot/quasar.js +++ b/src/boot/quasar.js @@ -52,9 +52,9 @@ export default boot(({ app }) => { if (env && env !== 'development') return; message = 'Duplicate request'; } - // Convey to Alex or Juan... + const additionalData = { - frontPath: stateQuery.route.name, + frontPath: '', backError: { config: error.config, data: error, @@ -70,14 +70,15 @@ export default boot(({ app }) => { flat: false, round: true, handler: async () => { + const locale = i18n.global.t; const reason = ref( response.data.error.code == 'ACCESS_DENIED' - ? i18n.global.t('cau.askPrivileges') + ? locale('cau.askPrivileges') : '' ); openConfirmationModal( - i18n.global.t('cau.title'), - i18n.global.t('cau.subtitle'), + locale('cau.title'), + locale('cau.subtitle'), async () => { await axios.post('OsTickets/send-to-support', { reason: reason.value, @@ -90,7 +91,7 @@ export default boot(({ app }) => { props: { modelValue: reason, 'onUpdate:modelValue': (val) => (reason.value = val), - label: i18n.global.t('cau.inputLabel'), + label: locale('cau.inputLabel'), class: 'full-width', required: true, }, diff --git a/src/components/NavBar.vue b/src/components/NavBar.vue index 6f8377d96..9b0393489 100644 --- a/src/components/NavBar.vue +++ b/src/components/NavBar.vue @@ -1,7 +1,6 @@ From a5d032f0224f4184bcf619762ff569656765bc0c Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 13 Nov 2024 17:29:19 +0100 Subject: [PATCH 05/13] feat: make additional data object --- src/boot/quasar.js | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/src/boot/quasar.js b/src/boot/quasar.js index 103b4812e..a018eede7 100644 --- a/src/boot/quasar.js +++ b/src/boot/quasar.js @@ -5,12 +5,10 @@ import qFormMixin from './qformMixin'; import keyShortcut from './keyShortcut'; import { i18n } from './i18n'; import useNotify from 'src/composables/useNotify.js'; -import { useStateQueryStore } from 'src/stores/useStateQueryStore'; import VnInput from 'src/components/common/VnInput.vue'; import { useVnConfirm } from 'src/composables/useVnConfirm'; const { notify } = useNotify(); -const stateQuery = useStateQueryStore(); const { openConfirmationModal } = useVnConfirm(); export default boot(({ app }) => { @@ -53,13 +51,25 @@ export default boot(({ app }) => { message = 'Duplicate request'; } + const { config, headers, request, status, statusText, data } = response || {}; + const { params, url, method, signal, headers: confHeaders } = config || {}; + const { message: resMessage, code, name } = data?.error || {}; const additionalData = { - frontPath: '', - backError: { - config: error.config, - data: error, + path: location.href, + message: resMessage, + code, + request: request?.responseURL, + status, + name, + statusText: statusText, + config: { + url, + method, + params, + headers: confHeaders, + aborted: signal.aborted, + version: headers?.['salix-version'], }, - httpRequest: error.request.response, }; const opts = { actions: [ @@ -72,9 +82,7 @@ export default boot(({ app }) => { handler: async () => { const locale = i18n.global.t; const reason = ref( - response.data.error.code == 'ACCESS_DENIED' - ? locale('cau.askPrivileges') - : '' + code == 'ACCESS_DENIED' ? locale('cau.askPrivileges') : '' ); openConfirmationModal( locale('cau.title'), From 81f1c447ad4152dfaf1eb03da686ebf8cb1f3b31 Mon Sep 17 00:00:00 2001 From: jorgep Date: Wed, 13 Nov 2024 17:45:02 +0100 Subject: [PATCH 06/13] fix: rollback --- src/stores/useStateQueryStore.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/stores/useStateQueryStore.js b/src/stores/useStateQueryStore.js index 9893d3264..d25dbb921 100644 --- a/src/stores/useStateQueryStore.js +++ b/src/stores/useStateQueryStore.js @@ -3,9 +3,7 @@ import { defineStore } from 'pinia'; export const useStateQueryStore = defineStore('stateQueryStore', () => { const queries = ref(new Set()); - const route = computed(() => - Array.from(queries.value).find((query) => query?.fullPath) - ); + function add(query) { queries.value.add(query); return query; @@ -29,6 +27,5 @@ export const useStateQueryStore = defineStore('stateQueryStore', () => { remove, queries, reset, - route, }; }); From fa43f270ca0bc266c1f9644e15a19209f7bb7e30 Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 14 Nov 2024 12:02:40 +0100 Subject: [PATCH 07/13] fix: prevent null --- src/boot/quasar.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/boot/quasar.js b/src/boot/quasar.js index a018eede7..720fc29de 100644 --- a/src/boot/quasar.js +++ b/src/boot/quasar.js @@ -67,7 +67,7 @@ export default boot(({ app }) => { method, params, headers: confHeaders, - aborted: signal.aborted, + aborted: signal?.aborted, version: headers?.['salix-version'], }, }; From 0fe740e415f3f15666fba18b4857adf8dd447de5 Mon Sep 17 00:00:00 2001 From: jorgep Date: Thu, 14 Nov 2024 13:20:23 +0100 Subject: [PATCH 08/13] fix: e2e --- src/pages/Worker/WorkerList.vue | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Worker/WorkerList.vue b/src/pages/Worker/WorkerList.vue index 02bea0231..81b231710 100644 --- a/src/pages/Worker/WorkerList.vue +++ b/src/pages/Worker/WorkerList.vue @@ -306,7 +306,7 @@ async function autofillBic(worker) { Date: Thu, 5 Dec 2024 08:28:43 +0100 Subject: [PATCH 09/13] fix: refs #7031 add test e2e --- .../integration/zone/zoneBasicData.spec.js | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/test/cypress/integration/zone/zoneBasicData.spec.js b/test/cypress/integration/zone/zoneBasicData.spec.js index c6151a49b..09ca691c9 100644 --- a/test/cypress/integration/zone/zoneBasicData.spec.js +++ b/test/cypress/integration/zone/zoneBasicData.spec.js @@ -1,5 +1,6 @@ describe('ZoneBasicData', () => { const notification = '.q-notification__message'; + const priceBasicData = '[data-cy="Price_input"]'; beforeEach(() => { cy.viewport(1280, 720); @@ -13,9 +14,21 @@ describe('ZoneBasicData', () => { cy.get(notification).should('contains.text', "can't be blank"); }); + it('should throw an error if the price is 0', () => { + cy.get(priceBasicData).type('0'); + cy.get('.q-btn-group > .q-btn--standard').click(); + cy.get(notification).should('Price must be greater than 0'); + }); + + it('should throw an error if the price is empty', () => { + cy.get(priceBasicData).clear(); + cy.get('.q-btn-group > .q-btn--standard').click(); + cy.get(notification).should('contains.text', 'cannot be blank'); + }); + it("should edit the basicData's zone", () => { cy.get('.q-card > :nth-child(1)').type(' modified'); cy.get('.q-btn-group > .q-btn--standard').click(); - cy.get(notification).should('contains.text', 'Data saved'); + cy.get(notification).should('Price must be greater than 0'); }); }); From a20afa5f35446792cf54921b5cc395e4fc16a295 Mon Sep 17 00:00:00 2001 From: carlossa Date: Mon, 9 Dec 2024 11:43:20 +0100 Subject: [PATCH 10/13] fix: refs #7031 fix zoneTest --- test/cypress/integration/zone/zoneBasicData.spec.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/test/cypress/integration/zone/zoneBasicData.spec.js b/test/cypress/integration/zone/zoneBasicData.spec.js index 09ca691c9..7f4f972f6 100644 --- a/test/cypress/integration/zone/zoneBasicData.spec.js +++ b/test/cypress/integration/zone/zoneBasicData.spec.js @@ -14,12 +14,6 @@ describe('ZoneBasicData', () => { cy.get(notification).should('contains.text', "can't be blank"); }); - it('should throw an error if the price is 0', () => { - cy.get(priceBasicData).type('0'); - cy.get('.q-btn-group > .q-btn--standard').click(); - cy.get(notification).should('Price must be greater than 0'); - }); - it('should throw an error if the price is empty', () => { cy.get(priceBasicData).clear(); cy.get('.q-btn-group > .q-btn--standard').click(); @@ -29,6 +23,6 @@ describe('ZoneBasicData', () => { it("should edit the basicData's zone", () => { cy.get('.q-card > :nth-child(1)').type(' modified'); cy.get('.q-btn-group > .q-btn--standard').click(); - cy.get(notification).should('Price must be greater than 0'); + cy.checkNotification('Data saved'); }); }); From 2fb179803c235d43cf39e0269f9ceb98c794c508 Mon Sep 17 00:00:00 2001 From: jorgep Date: Mon, 9 Dec 2024 13:42:00 +0100 Subject: [PATCH 11/13] refactor: add useCau composable --- src/boot/quasar.js | 71 ++----------------------------------- src/composables/useCau.js | 73 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 76 insertions(+), 68 deletions(-) create mode 100644 src/composables/useCau.js diff --git a/src/boot/quasar.js b/src/boot/quasar.js index a1ae1eb3a..547517682 100644 --- a/src/boot/quasar.js +++ b/src/boot/quasar.js @@ -1,25 +1,18 @@ -import { ref } from 'vue'; import axios from 'axios'; import { boot } from 'quasar/wrappers'; import qFormMixin from './qformMixin'; import keyShortcut from './keyShortcut'; -import { i18n } from './i18n'; -import useNotify from 'src/composables/useNotify.js'; -import VnInput from 'src/components/common/VnInput.vue'; -import { useVnConfirm } from 'src/composables/useVnConfirm'; import { QForm } from 'quasar'; import { QLayout } from 'quasar'; import mainShortcutMixin from './mainShortcutMixin'; - -const { notify } = useNotify(); -const { openConfirmationModal } = useVnConfirm(); +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; @@ -56,64 +49,6 @@ export default boot(({ app }) => { message = 'Duplicate request'; } - const { config, headers, request, status, statusText, data } = response || {}; - const { params, url, method, signal, headers: confHeaders } = config || {}; - const { message: resMessage, code, name } = data?.error || {}; - const additionalData = { - path: location.href, - 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, - }, - } - ); - }, - }, - ], - }; - notify(message ?? 'globals.error', 'negative', 'error', opts); + await useCau(response, message); }; }); 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); +} From 983c86ffa51e8f86625040ba466daeb2ef50e4f9 Mon Sep 17 00:00:00 2001 From: Jon Date: Thu, 12 Dec 2024 07:35:20 +0100 Subject: [PATCH 12/13] feat: added restore ticket function in ticket descriptor menu --- .../Ticket/Card/TicketDescriptorMenu.vue | 70 ++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/src/pages/Ticket/Card/TicketDescriptorMenu.vue b/src/pages/Ticket/Card/TicketDescriptorMenu.vue index 60a703f84..1a6a67347 100644 --- a/src/pages/Ticket/Card/TicketDescriptorMenu.vue +++ b/src/pages/Ticket/Card/TicketDescriptorMenu.vue @@ -1,6 +1,6 @@