From 2c98563cfabb8994a99e3ecbcc10e6f435ad8da8 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 20 Oct 2022 07:39:33 +0200 Subject: [PATCH 1/7] Add buttons to bottom-right --- modules/route/front/index/index.html | 50 +++++++++++++++------------- 1 file changed, 27 insertions(+), 23 deletions(-) diff --git a/modules/route/front/index/index.html b/modules/route/front/index/index.html index 7a64a9aff..b3e520aea 100644 --- a/modules/route/front/index/index.html +++ b/modules/route/front/index/index.html @@ -7,29 +7,6 @@ model="model" options="$ctrl.smartTableOptions" expr-builder="$ctrl.exprBuilder(param, value)"> - -
- - - - - - - -
-
@@ -190,6 +167,33 @@ tooltip-position="left"> + + + + + + + + + + + + From 8cbcb197bbd75b69c5f3aff54393725205a883e7 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 20 Oct 2022 08:14:11 +0200 Subject: [PATCH 2/7] fix downloadPDF wrong method --- modules/route/front/index/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/route/front/index/index.html b/modules/route/front/index/index.html index b3e520aea..cc76d22f2 100644 --- a/modules/route/front/index/index.html +++ b/modules/route/front/index/index.html @@ -180,7 +180,7 @@ From 28bd535e2b2590d665ba95d81a607aceddc54cbb Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 20 Oct 2022 15:04:25 +0200 Subject: [PATCH 3/7] Implemented SMS to route clients --- modules/route/back/methods/route/sendSms.js | 46 +++++++++++++ modules/route/back/models/route.js | 1 + modules/route/front/index.js | 1 + modules/route/front/index/index.html | 30 +++++++-- modules/route/front/index/index.js | 60 +++++++++++++++++ modules/route/front/index/locale/es.yml | 4 +- modules/route/front/sms/index.html | 45 +++++++++++++ modules/route/front/sms/index.js | 47 ++++++++++++++ modules/route/front/sms/index.spec.js | 71 +++++++++++++++++++++ modules/route/front/sms/locale/es.yml | 9 +++ modules/route/front/sms/style.scss | 5 ++ 11 files changed, 311 insertions(+), 8 deletions(-) create mode 100644 modules/route/back/methods/route/sendSms.js create mode 100644 modules/route/front/sms/index.html create mode 100644 modules/route/front/sms/index.js create mode 100644 modules/route/front/sms/index.spec.js create mode 100644 modules/route/front/sms/locale/es.yml create mode 100644 modules/route/front/sms/style.scss diff --git a/modules/route/back/methods/route/sendSms.js b/modules/route/back/methods/route/sendSms.js new file mode 100644 index 000000000..9a93b040e --- /dev/null +++ b/modules/route/back/methods/route/sendSms.js @@ -0,0 +1,46 @@ +/* eslint-disable no-console */ + +module.exports = Self => { + Self.remoteMethodCtx('sendSms', { + description: 'Sends a SMS to each client of the routes, each client only recieves the SMS once', + accessType: 'WRITE', + accepts: [{ + arg: 'id', + type: 'string', + required: true, + description: 'The routes Ids, is separated by commas', + http: {source: 'path'} + }, + { + arg: 'destination', + type: 'string', + description: 'A comma separated string of destinations', + required: true, + }, + { + arg: 'message', + type: 'string', + required: true, + }], + returns: { + type: 'object', + root: true + }, + http: { + path: `/:id/sendSms`, + verb: 'POST' + } + }); + + Self.sendSms = async(ctx, id, destination, message) => { + const targetClients = destination.split(','); + + const allSms = []; + for (let client of targetClients) { + let sms = await Self.app.models.Sms.send(ctx, client, message); + allSms.push(sms); + } + + return allSms; + }; +}; diff --git a/modules/route/back/models/route.js b/modules/route/back/models/route.js index f5406728a..08cabd30e 100644 --- a/modules/route/back/models/route.js +++ b/modules/route/back/models/route.js @@ -12,6 +12,7 @@ module.exports = Self => { require('../methods/route/updateWorkCenter')(Self); require('../methods/route/driverRoutePdf')(Self); require('../methods/route/driverRouteEmail')(Self); + require('../methods/route/sendSms')(Self); Self.validate('kmStart', validateDistance, { message: 'Distance must be lesser than 1000' diff --git a/modules/route/front/index.js b/modules/route/front/index.js index 55cb745e1..c43048df5 100644 --- a/modules/route/front/index.js +++ b/modules/route/front/index.js @@ -15,3 +15,4 @@ import './agency-term/index'; import './agency-term/createInvoiceIn'; import './agency-term-search-panel'; import './ticket-popup'; +import './sms'; diff --git a/modules/route/front/index/index.html b/modules/route/front/index/index.html index cc76d22f2..e9785d958 100644 --- a/modules/route/front/index/index.html +++ b/modules/route/front/index/index.html @@ -160,13 +160,6 @@
- - - - + + + + + + + +
+ + + + + e === ticket.clientFk).length > 0) + clientsFk.push(ticket.clientFk); + } + + for (let client of clientsFk) { + let currentClient = await this.$http.get(`Clients/${client}`); + clients.push(currentClient.data); + } + + let destination = ''; + let destinationFk = ''; + let routesId = ''; + + for (let client of clients) { + if (destination !== '') + destination = destination + ','; + if (destinationFk !== '') + destinationFk = destinationFk + ','; + destination = destination + client.phone; + destinationFk = destinationFk + client.id; + } + + for (let route of routes) { + if (routesId !== '') + routesId = routesId + ','; + routesId = routesId + route; + } + this.newSMS = Object.assign({ + routesId: routesId, + destinationFk: destinationFk, + destination: destination + }); + + this.$.sms.open(); + return true; + } catch (e) { + this.vnApp.showError(this.$t(e.message)); + return false; + } + } } Controller.$inject = ['$element', '$scope', 'vnReport']; diff --git a/modules/route/front/index/locale/es.yml b/modules/route/front/index/locale/es.yml index e4c5c8c55..3db84d81e 100644 --- a/modules/route/front/index/locale/es.yml +++ b/modules/route/front/index/locale/es.yml @@ -8,4 +8,6 @@ Hour finished: Hora fin Go to route: Ir a la ruta You must select a valid time: Debe seleccionar una hora válida You must select a valid date: Debe seleccionar una fecha válida -Mark as served: Marcar como servidas \ No newline at end of file +Mark as served: Marcar como servidas +Retrieving data from the routes: Recuperando datos de las rutas +Send SMS to all clients: Mandar sms a todos los clientes de las rutas \ No newline at end of file diff --git a/modules/route/front/sms/index.html b/modules/route/front/sms/index.html new file mode 100644 index 000000000..4f86b346f --- /dev/null +++ b/modules/route/front/sms/index.html @@ -0,0 +1,45 @@ + + +
+ + + + + + + + {{'Characters remaining' | translate}}: + + {{$ctrl.charactersRemaining()}} + + + +
+
+ + + + +
\ No newline at end of file diff --git a/modules/route/front/sms/index.js b/modules/route/front/sms/index.js new file mode 100644 index 000000000..701306071 --- /dev/null +++ b/modules/route/front/sms/index.js @@ -0,0 +1,47 @@ +import ngModule from '../module'; +import Component from 'core/lib/component'; +import './style.scss'; + +class Controller extends Component { + open() { + this.$.SMSDialog.show(); + } + + charactersRemaining() { + const element = this.$.message; + const value = element.input.value; + + const maxLength = 160; + const textAreaLength = new Blob([value]).size; + return maxLength - textAreaLength; + } + + onResponse() { + try { + if (!this.sms.destination) + throw new Error(`The destination can't be empty`); + if (!this.sms.message) + throw new Error(`The message can't be empty`); + if (this.charactersRemaining() < 0) + throw new Error(`The message it's too long`); + + this.$http.post(`Routes/${this.sms.routesId}/sendSms`, this.sms).then(res => { + this.vnApp.showMessage(this.$t('SMS sent!')); + + if (res.data) this.emit('send', {response: res.data}); + }); + } catch (e) { + this.vnApp.showError(this.$t(e.message)); + return false; + } + return true; + } +} + +ngModule.vnComponent('vnRouteSms', { + template: require('./index.html'), + controller: Controller, + bindings: { + sms: '<', + } +}); diff --git a/modules/route/front/sms/index.spec.js b/modules/route/front/sms/index.spec.js new file mode 100644 index 000000000..b133db04d --- /dev/null +++ b/modules/route/front/sms/index.spec.js @@ -0,0 +1,71 @@ +import './index'; + +describe('Ticket', () => { + describe('Component vnTicketSms', () => { + let controller; + let $httpBackend; + + beforeEach(ngModule('ticket')); + + beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { + $httpBackend = _$httpBackend_; + let $scope = $rootScope.$new(); + const $element = angular.element(''); + controller = $componentController('vnTicketSms', {$element, $scope}); + controller.$.message = { + input: { + value: 'My SMS' + } + }; + })); + + describe('onResponse()', () => { + it('should perform a POST query and show a success snackbar', () => { + let params = {ticketId: 11, destinationFk: 1101, destination: 111111111, message: 'My SMS'}; + controller.sms = {ticketId: 11, destinationFk: 1101, destination: 111111111, message: 'My SMS'}; + + jest.spyOn(controller.vnApp, 'showMessage'); + $httpBackend.expect('POST', `Tickets/11/sendSms`, params).respond(200, params); + + controller.onResponse(); + $httpBackend.flush(); + + expect(controller.vnApp.showMessage).toHaveBeenCalledWith('SMS sent!'); + }); + + it('should call onResponse without the destination and show an error snackbar', () => { + controller.sms = {destinationFk: 1101, message: 'My SMS'}; + + jest.spyOn(controller.vnApp, 'showError'); + + controller.onResponse(); + + expect(controller.vnApp.showError).toHaveBeenCalledWith(`The destination can't be empty`); + }); + + it('should call onResponse without the message and show an error snackbar', () => { + controller.sms = {destinationFk: 1101, destination: 222222222}; + + jest.spyOn(controller.vnApp, 'showError'); + + controller.onResponse(); + + expect(controller.vnApp.showError).toHaveBeenCalledWith(`The message can't be empty`); + }); + }); + + describe('charactersRemaining()', () => { + it('should return the characters remaining in a element', () => { + controller.$.message = { + input: { + value: 'My message 0€' + } + }; + + let result = controller.charactersRemaining(); + + expect(result).toEqual(145); + }); + }); + }); +}); diff --git a/modules/route/front/sms/locale/es.yml b/modules/route/front/sms/locale/es.yml new file mode 100644 index 000000000..4d6022921 --- /dev/null +++ b/modules/route/front/sms/locale/es.yml @@ -0,0 +1,9 @@ +Send SMS: Enviar SMS +Routes to notify: Rutas a notificar +Message: Mensaje +SMS sent!: ¡SMS enviado! +Characters remaining: Carácteres restantes +The destination can't be empty: El destinatario no puede estar vacio +The message can't be empty: El mensaje no puede estar vacio +The message it's too long: El mensaje es demasiado largo +Special characters like accents counts as a multiple: Carácteres especiales como los acentos cuentan como varios \ No newline at end of file diff --git a/modules/route/front/sms/style.scss b/modules/route/front/sms/style.scss new file mode 100644 index 000000000..84571a5f4 --- /dev/null +++ b/modules/route/front/sms/style.scss @@ -0,0 +1,5 @@ +@import "variables"; + +.SMSDialog { + min-width: 400px +} \ No newline at end of file From ca53ec7c238a5cd2bc3f8807504063acd9126a33 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Thu, 20 Oct 2022 15:04:59 +0200 Subject: [PATCH 4/7] Changed the location of the function --- modules/route/back/methods/route/sendSms.js | 34 +++++------ modules/route/front/index/index.html | 66 +++++++-------------- modules/route/front/index/index.js | 60 ------------------- modules/route/front/sms/index.html | 13 +--- modules/route/front/sms/index.js | 2 +- modules/route/front/sms/locale/es.yml | 2 +- modules/route/front/tickets/index.html | 39 ++++++++---- modules/route/front/tickets/index.js | 31 ++++++++++ 8 files changed, 99 insertions(+), 148 deletions(-) diff --git a/modules/route/back/methods/route/sendSms.js b/modules/route/back/methods/route/sendSms.js index 9a93b040e..fe881abd5 100644 --- a/modules/route/back/methods/route/sendSms.js +++ b/modules/route/back/methods/route/sendSms.js @@ -4,35 +4,29 @@ module.exports = Self => { Self.remoteMethodCtx('sendSms', { description: 'Sends a SMS to each client of the routes, each client only recieves the SMS once', accessType: 'WRITE', - accepts: [{ - arg: 'id', - type: 'string', - required: true, - description: 'The routes Ids, is separated by commas', - http: {source: 'path'} - }, - { - arg: 'destination', - type: 'string', - description: 'A comma separated string of destinations', - required: true, - }, - { - arg: 'message', - type: 'string', - required: true, - }], + accepts: [ + { + arg: 'destination', + type: 'string', + description: 'A comma separated string of destinations', + required: true, + }, + { + arg: 'message', + type: 'string', + required: true, + }], returns: { type: 'object', root: true }, http: { - path: `/:id/sendSms`, + path: `/sendSms`, verb: 'POST' } }); - Self.sendSms = async(ctx, id, destination, message) => { + Self.sendSms = async(ctx, destination, message) => { const targetClients = destination.split(','); const allSms = []; diff --git a/modules/route/front/index/index.html b/modules/route/front/index/index.html index e9785d958..7a64a9aff 100644 --- a/modules/route/front/index/index.html +++ b/modules/route/front/index/index.html @@ -7,6 +7,29 @@ model="model" options="$ctrl.smartTableOptions" expr-builder="$ctrl.exprBuilder(param, value)"> + +
+ + + + + + + +
+
@@ -160,42 +183,6 @@
- - - - - - - - - - - - - - - -
- - - - - e === ticket.clientFk).length > 0) - clientsFk.push(ticket.clientFk); - } - - for (let client of clientsFk) { - let currentClient = await this.$http.get(`Clients/${client}`); - clients.push(currentClient.data); - } - - let destination = ''; - let destinationFk = ''; - let routesId = ''; - - for (let client of clients) { - if (destination !== '') - destination = destination + ','; - if (destinationFk !== '') - destinationFk = destinationFk + ','; - destination = destination + client.phone; - destinationFk = destinationFk + client.id; - } - - for (let route of routes) { - if (routesId !== '') - routesId = routesId + ','; - routesId = routesId + route; - } - this.newSMS = Object.assign({ - routesId: routesId, - destinationFk: destinationFk, - destination: destination - }); - - this.$.sms.open(); - return true; - } catch (e) { - this.vnApp.showError(this.$t(e.message)); - return false; - } - } } Controller.$inject = ['$element', '$scope', 'vnReport']; diff --git a/modules/route/front/sms/index.html b/modules/route/front/sms/index.html index 4f86b346f..0d7dd7c11 100644 --- a/modules/route/front/sms/index.html +++ b/modules/route/front/sms/index.html @@ -1,19 +1,10 @@ + message="Send SMS to the selected tickets">
- - + { + this.$http.post(`Routes/sendSms`, this.sms).then(res => { this.vnApp.showMessage(this.$t('SMS sent!')); if (res.data) this.emit('send', {response: res.data}); diff --git a/modules/route/front/sms/locale/es.yml b/modules/route/front/sms/locale/es.yml index 4d6022921..0168a6eb6 100644 --- a/modules/route/front/sms/locale/es.yml +++ b/modules/route/front/sms/locale/es.yml @@ -1,4 +1,4 @@ -Send SMS: Enviar SMS +Send SMS to the selected tickets: Enviar SMS a los tickets seleccionados Routes to notify: Rutas a notificar Message: Mensaje SMS sent!: ¡SMS enviado! diff --git a/modules/route/front/tickets/index.html b/modules/route/front/tickets/index.html index 1f91276e7..29f5cd861 100644 --- a/modules/route/front/tickets/index.html +++ b/modules/route/front/tickets/index.html @@ -29,13 +29,18 @@ disabled="!$ctrl.isChecked" ng-click="$ctrl.deletePriority()" vn-tooltip="Delete priority" - icon="filter_alt_off"> + icon="filter_alt"> + + @@ -149,19 +154,29 @@ route="$ctrl.$params" parent-reload="$ctrl.$.model.refresh()"> - - - +
+ + + + + + +
- \ No newline at end of file + + + + \ No newline at end of file diff --git a/modules/route/front/tickets/index.js b/modules/route/front/tickets/index.js index e78d9b8b7..80f8ad4f4 100644 --- a/modules/route/front/tickets/index.js +++ b/modules/route/front/tickets/index.js @@ -161,6 +161,37 @@ class Controller extends Section { throw error; }); } + + async sendSms() { + try { + const clientsFk = []; + const clientsName = []; + const clients = []; + + const selectedTickets = this.getSelectedItems(this.$.$ctrl.tickets); + + for (let ticket of selectedTickets) { + clientsFk.push(ticket.clientFk); + let userContact = await this.$http.get(`Clients/${ticket.clientFk}`); + clientsName.push(userContact.data.name); + clients.push(userContact.data.phone); + } + + const destinationFk = String(clientsFk); + const destination = String(clients); + + this.newSMS = Object.assign({ + destinationFk: destinationFk, + destination: destination + }); + + this.$.sms.open(); + return true; + } catch (e) { + this.vnApp.showError(this.$t(e.message)); + return false; + } + } } ngModule.vnComponent('vnRouteTickets', { From 5bf425d8e351724463338ea536f94e8fc25cfa58 Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Mon, 24 Oct 2022 08:22:04 +0200 Subject: [PATCH 5/7] Front test and sms require client #4157 @1h30m --- modules/route/front/sms/index.spec.js | 14 +++++++------- modules/route/front/tickets/index.html | 1 + 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/modules/route/front/sms/index.spec.js b/modules/route/front/sms/index.spec.js index b133db04d..42bf30931 100644 --- a/modules/route/front/sms/index.spec.js +++ b/modules/route/front/sms/index.spec.js @@ -1,17 +1,17 @@ import './index'; -describe('Ticket', () => { - describe('Component vnTicketSms', () => { +describe('Route', () => { + describe('Component vnRouteSms', () => { let controller; let $httpBackend; - beforeEach(ngModule('ticket')); + beforeEach(ngModule('route')); beforeEach(inject(($componentController, $rootScope, _$httpBackend_) => { $httpBackend = _$httpBackend_; let $scope = $rootScope.$new(); const $element = angular.element(''); - controller = $componentController('vnTicketSms', {$element, $scope}); + controller = $componentController('vnRouteSms', {$element, $scope}); controller.$.message = { input: { value: 'My SMS' @@ -21,11 +21,11 @@ describe('Ticket', () => { describe('onResponse()', () => { it('should perform a POST query and show a success snackbar', () => { - let params = {ticketId: 11, destinationFk: 1101, destination: 111111111, message: 'My SMS'}; - controller.sms = {ticketId: 11, destinationFk: 1101, destination: 111111111, message: 'My SMS'}; + let params = {destinationFk: 1101, destination: 111111111, message: 'My SMS'}; + controller.sms = {destinationFk: 1101, destination: 111111111, message: 'My SMS'}; jest.spyOn(controller.vnApp, 'showMessage'); - $httpBackend.expect('POST', `Tickets/11/sendSms`, params).respond(200, params); + $httpBackend.expect('POST', `Routes/sendSms`, params).respond(200, params); controller.onResponse(); $httpBackend.flush(); diff --git a/modules/route/front/tickets/index.html b/modules/route/front/tickets/index.html index 29f5cd861..a3d65772a 100644 --- a/modules/route/front/tickets/index.html +++ b/modules/route/front/tickets/index.html @@ -37,6 +37,7 @@ icon="format_list_numbered"> From 3cfa56d610f3558ce8212475bdbd75ac22ef5cdb Mon Sep 17 00:00:00 2001 From: Pau Navarro Date: Tue, 25 Oct 2022 13:15:19 +0200 Subject: [PATCH 6/7] Add deliveryBoss ACL to the front --- modules/route/front/tickets/index.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/modules/route/front/tickets/index.html b/modules/route/front/tickets/index.html index a3d65772a..dae894ac7 100644 --- a/modules/route/front/tickets/index.html +++ b/modules/route/front/tickets/index.html @@ -37,6 +37,8 @@ icon="format_list_numbered"> Date: Thu, 10 Nov 2022 07:23:08 +0100 Subject: [PATCH 7/7] Added requestes changes refs #4157 --- modules/route/back/methods/route/sendSms.js | 1 - 1 file changed, 1 deletion(-) diff --git a/modules/route/back/methods/route/sendSms.js b/modules/route/back/methods/route/sendSms.js index fe881abd5..d1c3efa35 100644 --- a/modules/route/back/methods/route/sendSms.js +++ b/modules/route/back/methods/route/sendSms.js @@ -1,4 +1,3 @@ -/* eslint-disable no-console */ module.exports = Self => { Self.remoteMethodCtx('sendSms', {