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/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