From 467c4e997c720a277da382ce6cebcac7c5f8dfcc Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 30 Jun 2023 14:24:50 +0200 Subject: [PATCH 1/5] refs #5941 feat: when error can send email to support --- back/methods/osticket/sendToSupport.js | 63 ++++++++++++++++++++ back/models/osticket.js | 1 + front/core/components/snackbar/snackbar.html | 36 ++++++++++- front/core/components/snackbar/snackbar.js | 31 +++++++++- front/core/components/snackbar/style.scss | 6 +- front/core/services/app.js | 4 +- front/salix/components/app/app.js | 8 +-- front/salix/module.js | 8 ++- modules/item/back/methods/item/filter.js | 4 +- 9 files changed, 148 insertions(+), 13 deletions(-) create mode 100644 back/methods/osticket/sendToSupport.js diff --git a/back/methods/osticket/sendToSupport.js b/back/methods/osticket/sendToSupport.js new file mode 100644 index 000000000..516313ac6 --- /dev/null +++ b/back/methods/osticket/sendToSupport.js @@ -0,0 +1,63 @@ +const smtp = require('vn-print/core/smtp'); +const config = require('vn-print/core/config'); + +module.exports = Self => { + Self.remoteMethodCtx('sendToSupport', { + description: 'Send mail to support', + accessType: 'WRITE', + accepts: [ + { + arg: 'subject', + type: 'string', + required: true, + description: 'The subject' + }, + { + arg: 'reason', + type: 'string', + description: 'The reason' + }, + { + arg: 'additionalData', + type: 'object', + required: true, + description: 'The additional data' + } + ], + returns: { + type: 'object', + root: true + }, + http: { + path: `/send-to-support`, + verb: 'POST' + } + }); + + Self.sendToSupport = async(ctx, subject, reason, additionalData) => { + const emailUser = + await Self.app.models.EmailUser.findById(ctx.req.accessToken.userId, {fields: ['email']}); + + let html = `Motivo:
${reason}
`; + for (const data in additionalData) { + tryJson(additionalData[data]); + html += `${data}:
${tryJson(additionalData[data])}
`; + } + console.log(subject, reason, additionalData); + console.log(html); + smtp.send({ + to: config.app.reportEmail, + replyTo: emailUser.email, + subject: '[Support-Salix] ' + subject, + html + }); + }; + + function tryJson(value) { + try { + return JSON.parse(value); + } catch (e) { + return value; + } + } +}; diff --git a/back/models/osticket.js b/back/models/osticket.js index 50e429160..2a4b7bbb5 100644 --- a/back/models/osticket.js +++ b/back/models/osticket.js @@ -1,4 +1,5 @@ module.exports = Self => { require('../methods/osticket/osTicketReportEmail')(Self); require('../methods/osticket/closeTicket')(Self); + require('../methods/osticket/sendToSupport')(Self); }; diff --git a/front/core/components/snackbar/snackbar.html b/front/core/components/snackbar/snackbar.html index 8ef5891bc..41ae6ddbd 100644 --- a/front/core/components/snackbar/snackbar.html +++ b/front/core/components/snackbar/snackbar.html @@ -1 +1,35 @@ -
\ No newline at end of file +
+ + +
+
Open CAU
+ + + + + + + + + + + {{'Este cau contiene más información relevante para el equipo de informática' | translate}}: + + +
+
+ + + + +
diff --git a/front/core/components/snackbar/snackbar.js b/front/core/components/snackbar/snackbar.js index e68c22f3f..19ce4ea54 100644 --- a/front/core/components/snackbar/snackbar.js +++ b/front/core/components/snackbar/snackbar.js @@ -27,6 +27,18 @@ export default class Controller extends Component { setTimeout(() => element.classList.add('shown'), 30); shape.element = element; + if (data.additionalData) { + let supportButton = document.createElement('i'); + supportButton.setAttribute('class', 'material-icons'); + supportButton.addEventListener('click', () => this.onButtonClick(this.$.supportDialog.show())); + element.appendChild(supportButton); + + let buttonIcon = 'support_agent'; + buttonIcon = document.createTextNode(buttonIcon); + supportButton.appendChild(buttonIcon); + this.$.supportDialog.additionalData = data.additionalData; + } + if (shape.type) element.classList.add(shape.type); @@ -95,7 +107,7 @@ export default class Controller extends Component { clearTimeout(shape.hideTimeout); shape.hideTimeout = setTimeout( - () => this.hide(shape), shape.timeout || 3000); + () => this.hide(shape), shape.timeout || 5000); this.lastShape = shape; } @@ -142,6 +154,23 @@ export default class Controller extends Component { else this.hide(shape); } + + sendToSupport() { + const supportDialog = this.$.supportDialog; + console.log(this.$.supportDialog.subject); + console.log(this.$.supportDialog.reason); + console.log(this.$.supportDialog.additionalData); + console.log({ + subject: supportDialog.subject, + reason: supportDialog.reason, + additionalData: supportDialog.additionalData + }); + this.$http.post('Ostickets/send-to-support', { + subject: supportDialog.subject, + reason: supportDialog.reason, + additionalData: supportDialog.additionalData + }); + } } ngModule.vnComponent('vnSnackbar', { diff --git a/front/core/components/snackbar/style.scss b/front/core/components/snackbar/style.scss index 23e8223e5..d02886fd1 100644 --- a/front/core/components/snackbar/style.scss +++ b/front/core/components/snackbar/style.scss @@ -20,11 +20,11 @@ vn-snackbar .shape { margin-bottom: 15px; color: white; padding: 12px 25px 12px 12px; - + & > .text { text-align: center; - vn-chip { + vn-chip { position: absolute; left: -16px; top: -16px; @@ -64,4 +64,4 @@ vn-snackbar .shape { top: 0; right: 0 } -} \ No newline at end of file +} diff --git a/front/core/services/app.js b/front/core/services/app.js index fb0a08777..bffdad108 100644 --- a/front/core/services/app.js +++ b/front/core/services/app.js @@ -23,9 +23,9 @@ export default class App { this.logger.showSuccess(message); } - showError(message) { + showError(message, additionalData) { if (this.logger) - this.logger.showError(message); + this.logger.showError(message, additionalData); } pushLoader() { diff --git a/front/salix/components/app/app.js b/front/salix/components/app/app.js index 97384d1e1..ca8fac751 100644 --- a/front/salix/components/app/app.js +++ b/front/salix/components/app/app.js @@ -25,15 +25,15 @@ export default class App extends Component { } showMessage(message) { - this.$.snackbar.show({message: message}); + this.$.snackbar.show({message}); } showSuccess(message) { - this.$.snackbar.showSuccess({message: message}); + this.$.snackbar.showSuccess({message}); } - showError(message) { - this.$.snackbar.showError({message: message}); + showError(message, additionalData) { + this.$.snackbar.showError({message, additionalData}); } } diff --git a/front/salix/module.js b/front/salix/module.js index 01df01a67..422c2741e 100644 --- a/front/salix/module.js +++ b/front/salix/module.js @@ -148,7 +148,13 @@ function $exceptionHandler(vnApp, $window, $state, $injector) { if (messageT) message = $translate.instant(messageT); - vnApp.showError(message); + + const additonalData = { + frontPath: $state.current.name, + httpRequest: cause.replace('Possibly unhandled rejection: ', ''), + backError: JSON.stringify(exception) + }; + vnApp.showError(message, additonalData); }; } ngModule.factory('$exceptionHandler', $exceptionHandler); diff --git a/modules/item/back/methods/item/filter.js b/modules/item/back/methods/item/filter.js index c0b1cc0d9..9a60f6264 100644 --- a/modules/item/back/methods/item/filter.js +++ b/modules/item/back/methods/item/filter.js @@ -2,6 +2,7 @@ const ParameterizedSQL = require('loopback-connector').ParameterizedSQL; const buildFilter = require('vn-loopback/util/filter').buildFilter; const mergeFilters = require('vn-loopback/util/filter').mergeFilters; +const UserError = require('vn-loopback/util/user-error'); module.exports = Self => { Self.remoteMethodCtx('filter', { @@ -88,6 +89,7 @@ module.exports = Self => { const conn = Self.dataSource.connector; const models = Self.app.models; const myOptions = {}; + throw new UserError(`You don't have enough privileges`); if (typeof options == 'object') Object.assign(myOptions, options); @@ -145,7 +147,7 @@ module.exports = Self => { const stmts = []; const stmt = new ParameterizedSQL( - `SELECT + `SELECT i.id, i.image, i.name, -- 2.40.1 From 9097a1dc289decb4e585f14afa3a8408d12d5eb2 Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 14 Jul 2023 14:30:08 +0200 Subject: [PATCH 2/5] refs #5941 feat: sendToSuppor component and fix CSS and JSON format --- back/methods/osticket/sendToSupport.js | 34 ++++++++--------- front/core/components/index.js | 1 + front/core/components/snackbar/snackbar.html | 38 ++----------------- front/core/components/snackbar/snackbar.js | 23 ++--------- front/core/components/snackbar/style.scss | 12 ++++++ .../core/components/support-dialog/index.html | 22 +++++++++++ front/core/components/support-dialog/index.js | 27 +++++++++++++ front/core/locale/es.yml | 2 + front/salix/module.js | 3 +- modules/item/back/methods/item/filter.js | 2 - modules/route/front/roadmap/index/index.js | 2 - modules/worker/front/time-control/index.html | 2 +- 12 files changed, 91 insertions(+), 77 deletions(-) create mode 100644 front/core/components/support-dialog/index.html create mode 100644 front/core/components/support-dialog/index.js diff --git a/back/methods/osticket/sendToSupport.js b/back/methods/osticket/sendToSupport.js index 516313ac6..320691e23 100644 --- a/back/methods/osticket/sendToSupport.js +++ b/back/methods/osticket/sendToSupport.js @@ -6,12 +6,6 @@ module.exports = Self => { description: 'Send mail to support', accessType: 'WRITE', accepts: [ - { - arg: 'subject', - type: 'string', - required: true, - description: 'The subject' - }, { arg: 'reason', type: 'string', @@ -34,29 +28,35 @@ module.exports = Self => { } }); - Self.sendToSupport = async(ctx, subject, reason, additionalData) => { + Self.sendToSupport = async(ctx, reason, additionalData) => { const emailUser = await Self.app.models.EmailUser.findById(ctx.req.accessToken.userId, {fields: ['email']}); let html = `Motivo:
${reason}
`; - for (const data in additionalData) { - tryJson(additionalData[data]); - html += `${data}:
${tryJson(additionalData[data])}
`; - } - console.log(subject, reason, additionalData); - console.log(html); + + for (const data in additionalData) + html += `${data}:
${tryParse(additionalData[data])}
`; + + const subjectReason = JSON.parse(additionalData?.httpRequest)?.data?.error; smtp.send({ to: config.app.reportEmail, replyTo: emailUser.email, - subject: '[Support-Salix] ' + subject, + subject: + '[Support-Salix] ' + + additionalData?.frontPath + ' ' + + subjectReason?.name + ':' + + subjectReason?.message, html }); }; - function tryJson(value) { + function tryParse(value) { try { - return JSON.parse(value); - } catch (e) { + try { + value = JSON.parse(value); + } catch {} + return JSON.stringify(value, null, ' ').split('\n').join('
'); + } catch { return value; } } diff --git a/front/core/components/index.js b/front/core/components/index.js index 45d182121..e1b58374e 100644 --- a/front/core/components/index.js +++ b/front/core/components/index.js @@ -55,3 +55,4 @@ import './datalist'; import './contextmenu'; import './rating'; import './smart-table'; +import './support-dialog'; diff --git a/front/core/components/snackbar/snackbar.html b/front/core/components/snackbar/snackbar.html index 41ae6ddbd..a822badc3 100644 --- a/front/core/components/snackbar/snackbar.html +++ b/front/core/components/snackbar/snackbar.html @@ -1,35 +1,5 @@
- - -
-
Open CAU
- - - - - - - - - - - {{'Este cau contiene más información relevante para el equipo de informática' | translate}}: - - -
-
- - - - -
+ + diff --git a/front/core/components/snackbar/snackbar.js b/front/core/components/snackbar/snackbar.js index 19ce4ea54..7f4583188 100644 --- a/front/core/components/snackbar/snackbar.js +++ b/front/core/components/snackbar/snackbar.js @@ -28,15 +28,15 @@ export default class Controller extends Component { shape.element = element; if (data.additionalData) { + this.additionalData = data.additionalData; let supportButton = document.createElement('i'); - supportButton.setAttribute('class', 'material-icons'); - supportButton.addEventListener('click', () => this.onButtonClick(this.$.supportDialog.show())); + supportButton.setAttribute('class', 'material-icons clickable'); + supportButton.addEventListener('click', () => this.$.supportDialog.show()); element.appendChild(supportButton); let buttonIcon = 'support_agent'; buttonIcon = document.createTextNode(buttonIcon); supportButton.appendChild(buttonIcon); - this.$.supportDialog.additionalData = data.additionalData; } if (shape.type) @@ -154,23 +154,6 @@ export default class Controller extends Component { else this.hide(shape); } - - sendToSupport() { - const supportDialog = this.$.supportDialog; - console.log(this.$.supportDialog.subject); - console.log(this.$.supportDialog.reason); - console.log(this.$.supportDialog.additionalData); - console.log({ - subject: supportDialog.subject, - reason: supportDialog.reason, - additionalData: supportDialog.additionalData - }); - this.$http.post('Ostickets/send-to-support', { - subject: supportDialog.subject, - reason: supportDialog.reason, - additionalData: supportDialog.additionalData - }); - } } ngModule.vnComponent('vnSnackbar', { diff --git a/front/core/components/snackbar/style.scss b/front/core/components/snackbar/style.scss index d02886fd1..aed41c4cf 100644 --- a/front/core/components/snackbar/style.scss +++ b/front/core/components/snackbar/style.scss @@ -20,6 +20,10 @@ vn-snackbar .shape { margin-bottom: 15px; color: white; padding: 12px 25px 12px 12px; + display: flex ; + flex-direction: row; + justify-content: center; + align-items: center; & > .text { text-align: center; @@ -64,4 +68,12 @@ vn-snackbar .shape { top: 0; right: 0 } + + .clickable{ + background-color: $color-main; + padding: 6px; + border-radius: 50%; + cursor: pointer; + margin-right: 7px; + } } diff --git a/front/core/components/support-dialog/index.html b/front/core/components/support-dialog/index.html new file mode 100644 index 000000000..87887aa6f --- /dev/null +++ b/front/core/components/support-dialog/index.html @@ -0,0 +1,22 @@ + +
+
Send cau
+ + + + + + + {{'This email contains more relevant information for the IT team' | translate}} + + +
+
+ + + + diff --git a/front/core/components/support-dialog/index.js b/front/core/components/support-dialog/index.js new file mode 100644 index 000000000..eaaab047f --- /dev/null +++ b/front/core/components/support-dialog/index.js @@ -0,0 +1,27 @@ +import ngModule from '../../module'; +import Dialog from '../dialog'; + +export default class Controller extends Dialog { + constructor($element, $, $transclude) { + super($element, $, $transclude); + } + + responseHandler(response) { + this.$http.post('Ostickets/send-to-support', { + reason: this.reason, + additionalData: this.additionalData + }) + .then(() => super.responseHandler(response)) + .then(() => this.vnApp.showSuccess(this.$t('Email sended!'))); + } +} + +Controller.$inject = ['$element', '$scope', '$transclude']; + +ngModule.vnComponent('vnSupportDialog', { + slotTemplate: require('./index.html'), + controller: Controller, + bindings: { + additionalData: ' { Self.remoteMethodCtx('filter', { @@ -89,7 +88,6 @@ module.exports = Self => { const conn = Self.dataSource.connector; const models = Self.app.models; const myOptions = {}; - throw new UserError(`You don't have enough privileges`); if (typeof options == 'object') Object.assign(myOptions, options); diff --git a/modules/route/front/roadmap/index/index.js b/modules/route/front/roadmap/index/index.js index 3ffc5b4b1..c5f5ef9d1 100644 --- a/modules/route/front/roadmap/index/index.js +++ b/modules/route/front/roadmap/index/index.js @@ -46,8 +46,6 @@ class Controller extends Section { } deleteRoadmaps() { - console.log(this.checked); - for (const roadmap of this.checked) { this.$http.delete(`Roadmaps/${roadmap.id}`) .then(() => this.$.model.refresh()) diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html index 5f0855ee6..0dc85f144 100644 --- a/modules/worker/front/time-control/index.html +++ b/modules/worker/front/time-control/index.html @@ -24,7 +24,7 @@ ng-style="::{backgroundColor: weekday.event.color}">
- {{::weekday.event.name}} + {{::weekday.event}}
-- 2.40.1 From 858a3a3a452bc1e9732d52a1bb50f8a95aeea018 Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 17 Jul 2023 07:09:31 +0200 Subject: [PATCH 3/5] refs #5941 typo --- modules/worker/front/time-control/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/worker/front/time-control/index.html b/modules/worker/front/time-control/index.html index 0dc85f144..5f0855ee6 100644 --- a/modules/worker/front/time-control/index.html +++ b/modules/worker/front/time-control/index.html @@ -24,7 +24,7 @@ ng-style="::{backgroundColor: weekday.event.color}">
- {{::weekday.event}} + {{::weekday.event.name}}
-- 2.40.1 From ad5c0218320045413ee44b2d7b7d34accf07d77e Mon Sep 17 00:00:00 2001 From: alexm Date: Mon, 17 Jul 2023 07:10:26 +0200 Subject: [PATCH 4/5] refs #5941 duplicate code --- front/salix/module.js | 1 - 1 file changed, 1 deletion(-) diff --git a/front/salix/module.js b/front/salix/module.js index f22ca8a60..2bcac89f9 100644 --- a/front/salix/module.js +++ b/front/salix/module.js @@ -149,7 +149,6 @@ function $exceptionHandler(vnApp, $window, $state, $injector) { if (messageT) message = $translate.instant(messageT); - cause = cause.replace('Possibly unhandled rejection: ', ''); const additonalData = { frontPath: $state.current.name, httpRequest: cause.replace('Possibly unhandled rejection: ', ''), -- 2.40.1 From 4719922883b4126491e8128d32cb243422d344ca Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 11 Aug 2023 13:20:02 +0200 Subject: [PATCH 5/5] refs #5941 fix(support-dialog): change message, test: fix e2e --- front/core/components/support-dialog/index.html | 4 ++-- front/core/locale/en.yml | 3 ++- front/core/locale/es.yml | 3 ++- front/salix/module.js | 2 +- 4 files changed, 7 insertions(+), 5 deletions(-) diff --git a/front/core/components/support-dialog/index.html b/front/core/components/support-dialog/index.html index 87887aa6f..d03e1b7f2 100644 --- a/front/core/components/support-dialog/index.html +++ b/front/core/components/support-dialog/index.html @@ -3,7 +3,7 @@
Send cau
@@ -11,7 +11,7 @@ - {{'This email contains more relevant information for the IT team' | translate}} + {{'By sending this ticket, all the data related to the error, the section, the user, etc., are already sent.' | translate}} diff --git a/front/core/locale/en.yml b/front/core/locale/en.yml index 99a9b8049..3f6cb7d71 100644 --- a/front/core/locale/en.yml +++ b/front/core/locale/en.yml @@ -13,4 +13,5 @@ Finalize: Finalize Previous: Back Load more: Load more Auto-scroll interrupted, please adjust the search: Auto-scroll interrupted, please adjust the search -General search: General search \ No newline at end of file +General search: General search +ExplainReason: Explain the reason why this error should not occur diff --git a/front/core/locale/es.yml b/front/core/locale/es.yml index 534989f4d..e9c2311b4 100644 --- a/front/core/locale/es.yml +++ b/front/core/locale/es.yml @@ -65,4 +65,5 @@ No data: Sin datos Undo changes: Deshacer cambios Load more results: Cargar más resultados Send cau: Enviar cau -This email contains more relevant information for the IT team: Este correo contiene más información relevante para el equipo de informática +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 +ExplainReason: Explique el motivo por el que no deberia aparecer este fallo diff --git a/front/salix/module.js b/front/salix/module.js index 2bcac89f9..f8fa0faf0 100644 --- a/front/salix/module.js +++ b/front/salix/module.js @@ -151,7 +151,7 @@ function $exceptionHandler(vnApp, $window, $state, $injector) { const additonalData = { frontPath: $state.current.name, - httpRequest: cause.replace('Possibly unhandled rejection: ', ''), + httpRequest: cause?.replace('Possibly unhandled rejection: ', ''), backError: exception }; vnApp.showError(message, additonalData); -- 2.40.1