Merge pull request '2663 - Drag & drop ticket to route index' (#488) from 2663-route_dragdrop into dev
gitea/salix/pipeline/head This commit looks good
Details
gitea/salix/pipeline/head This commit looks good
Details
Reviewed-on: #488 Reviewed-by: Carlos Jimenez Ruiz <carlosjr@verdnatura.es>
This commit is contained in:
commit
e70b8a80e1
|
@ -163,5 +163,6 @@
|
|||
"ASSIGN_ZONE_FIRST": "Asigna una zona primero",
|
||||
"You can not select this payment method without a registered bankery account": "No se puede utilizar este método de pago si no has registrado una cuenta bancaria",
|
||||
"You can't upload images on the test environment": "No puedes subir imágenes en el entorno de pruebas",
|
||||
"The selected ticket is not suitable for this route": "El ticket seleccionado no es apto para esta ruta",
|
||||
"Sorts whole route": "Reordena ruta entera"
|
||||
}
|
|
@ -1,18 +1,18 @@
|
|||
const UserError = require('vn-loopback/util/user-error');
|
||||
|
||||
module.exports = Self => {
|
||||
Self.remoteMethod('ticketToRoute', {
|
||||
Self.remoteMethod('insertTicket', {
|
||||
description: 'Check if the ticket can be insert into the route and insert it',
|
||||
accessType: 'READ',
|
||||
accepts: [{
|
||||
arg: 'ticketId',
|
||||
arg: 'routeId',
|
||||
type: 'number',
|
||||
required: true,
|
||||
description: 'ticketId ',
|
||||
description: 'The route id',
|
||||
http: {source: 'path'}
|
||||
},
|
||||
{
|
||||
arg: 'routeId',
|
||||
arg: 'ticketId',
|
||||
type: 'number',
|
||||
required: true
|
||||
}],
|
||||
|
@ -21,12 +21,12 @@ module.exports = Self => {
|
|||
root: true
|
||||
},
|
||||
http: {
|
||||
path: `/:ticketId/ticketToRoute`,
|
||||
path: `/:routeId/insertTicket`,
|
||||
verb: 'PATCH'
|
||||
}
|
||||
});
|
||||
|
||||
Self.ticketToRoute = async(ticketId, routeId) => {
|
||||
Self.insertTicket = async(routeId, ticketId) => {
|
||||
const models = Self.app.models;
|
||||
|
||||
const route = await models.Route.findById(routeId);
|
||||
|
@ -43,9 +43,10 @@ module.exports = Self => {
|
|||
landed: {between: [minDate, maxDate]},
|
||||
}
|
||||
});
|
||||
|
||||
if (!ticket)
|
||||
throw new UserError('The selected ticket is not suitable for this route');
|
||||
|
||||
return await ticket.updateAttribute('routeFk', route.id);
|
||||
return ticket.updateAttribute('routeFk', route.id);
|
||||
};
|
||||
};
|
|
@ -1,7 +1,7 @@
|
|||
const app = require('vn-loopback/server/server');
|
||||
const LoopBackContext = require('loopback-context');
|
||||
|
||||
describe('route ticketToRoute()', () => {
|
||||
describe('route insertTicket()', () => {
|
||||
const deliveryId = 56;
|
||||
let originalTicket;
|
||||
const routeId = 2;
|
||||
|
@ -30,7 +30,7 @@ describe('route ticketToRoute()', () => {
|
|||
originalTicket = await app.models.Ticket.findById(14);
|
||||
|
||||
const ticketId = 14;
|
||||
const result = await app.models.Route.ticketToRoute(ticketId, routeId);
|
||||
const result = await app.models.Route.insertTicket(routeId, ticketId);
|
||||
|
||||
expect(result.routeFk).toEqual(2);
|
||||
});
|
||||
|
@ -40,7 +40,7 @@ describe('route ticketToRoute()', () => {
|
|||
let error;
|
||||
|
||||
try {
|
||||
await app.models.Route.ticketToRoute(ticketId, routeId);
|
||||
await app.models.Route.insertTicket(routeId, ticketId);
|
||||
} catch (e) {
|
||||
error = e.message;
|
||||
}
|
|
@ -5,7 +5,7 @@ module.exports = Self => {
|
|||
require('../methods/route/guessPriority')(Self);
|
||||
require('../methods/route/updateVolume')(Self);
|
||||
require('../methods/route/getDeliveryPoint')(Self);
|
||||
require('../methods/route/ticketToRoute')(Self);
|
||||
require('../methods/route/insertTicket')(Self);
|
||||
|
||||
Self.validate('kmStart', validateDistance, {
|
||||
message: 'Distance must be lesser than 1000'
|
||||
|
|
|
@ -26,7 +26,8 @@
|
|||
<vn-tbody>
|
||||
<a ng-repeat="route in model.data"
|
||||
class="clickable vn-tr search-result"
|
||||
ui-sref="route.card.summary({id: {{::route.id}}})">
|
||||
ui-sref="route.card.summary({id: {{::route.id}}})"
|
||||
ng-attr-id="{{::route.id}}" vn-droppable="$ctrl.onDrop($event)">
|
||||
<vn-td shrink>
|
||||
<vn-check
|
||||
ng-model="route.checked"
|
||||
|
|
|
@ -5,6 +5,7 @@ export default class Controller extends Section {
|
|||
constructor($element, $, vnReport) {
|
||||
super($element, $);
|
||||
this.vnReport = vnReport;
|
||||
this.droppableElement = 'a.vn-tr';
|
||||
}
|
||||
|
||||
preview(route) {
|
||||
|
@ -38,6 +39,41 @@ export default class Controller extends Section {
|
|||
routeId: routesId
|
||||
});
|
||||
}
|
||||
|
||||
onDrop($event) {
|
||||
const target = $event.target;
|
||||
const droppable = target.closest(this.droppableElement);
|
||||
const ticketId = $event.dataTransfer.getData('Text');
|
||||
const routeId = droppable.id;
|
||||
|
||||
if (isNaN(ticketId)) {
|
||||
const regexp = new RegExp(/\/ticket\/([0-9]+)\//i);
|
||||
const matches = ticketId.match(regexp);
|
||||
|
||||
if (matches && matches.length)
|
||||
this.insert(routeId, matches[1]);
|
||||
else
|
||||
this.vnApp.showError(this.$t('Ticket not found'));
|
||||
}
|
||||
|
||||
if (!isNaN(ticketId))
|
||||
this.insert(routeId, ticketId);
|
||||
}
|
||||
|
||||
insert(routeId, ticketId) {
|
||||
routeId = parseInt(routeId);
|
||||
ticketId = parseInt(ticketId);
|
||||
|
||||
const query = `Routes/${routeId}/insertTicket`;
|
||||
return this.$http.patch(query, {ticketId}).then(() => {
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
this.$.model.refresh();
|
||||
}).catch(error => {
|
||||
if (error.status == 404)
|
||||
return this.vnApp.showError(this.$t('Ticket not found'));
|
||||
throw error;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Controller.$inject = ['$element', '$scope', 'vnReport'];
|
||||
|
|
|
@ -3,10 +3,12 @@ import crudModel from 'core/mocks/crud-model';
|
|||
|
||||
describe('Component vnRouteIndex', () => {
|
||||
let controller;
|
||||
let $httpBackend;
|
||||
|
||||
beforeEach(ngModule('route'));
|
||||
|
||||
beforeEach(inject($componentController => {
|
||||
beforeEach(inject(($componentController, _$httpBackend_) => {
|
||||
$httpBackend = _$httpBackend_;
|
||||
const $element = angular.element('<vn-route-index></vn-route-index>');
|
||||
controller = $componentController('vnRouteIndex', {$element});
|
||||
controller.$.model = crudModel;
|
||||
|
@ -57,4 +59,83 @@ describe('Component vnRouteIndex', () => {
|
|||
expect(controller.vnReport.show).toHaveBeenCalledWith('driver-route', expectedParams);
|
||||
});
|
||||
});
|
||||
|
||||
describe('onDrop()', () => {
|
||||
it('should call the insert method when dragging a ticket number', () => {
|
||||
jest.spyOn(controller, 'insert');
|
||||
|
||||
const routeId = '1';
|
||||
const expectedTicketId = '16';
|
||||
const draggedElement = '16';
|
||||
const droppable = document.createElement('a');
|
||||
droppable.setAttribute('id', 1);
|
||||
droppable.classList.add('vn-tr');
|
||||
|
||||
const $event = {
|
||||
dataTransfer: {
|
||||
getData: () => draggedElement
|
||||
},
|
||||
target: droppable
|
||||
};
|
||||
controller.onDrop($event);
|
||||
|
||||
expect(controller.insert).toHaveBeenCalledWith(routeId, expectedTicketId);
|
||||
});
|
||||
|
||||
it('should call the insert method when dragging a ticket link', () => {
|
||||
jest.spyOn(controller, 'insert');
|
||||
|
||||
const routeId = '1';
|
||||
const expectedTicketId = '11';
|
||||
const draggedElement = 'http://arkamcity.com/#!/ticket/11/summary';
|
||||
const droppable = document.createElement('a');
|
||||
droppable.setAttribute('id', 1);
|
||||
droppable.classList.add('vn-tr');
|
||||
|
||||
const $event = {
|
||||
dataTransfer: {
|
||||
getData: () => draggedElement
|
||||
},
|
||||
target: droppable
|
||||
};
|
||||
controller.onDrop($event);
|
||||
|
||||
expect(controller.insert).toHaveBeenCalledWith(routeId, expectedTicketId);
|
||||
});
|
||||
|
||||
it('should throw an error when dragging an invalid ticket link', () => {
|
||||
jest.spyOn(controller.vnApp, 'showError');
|
||||
|
||||
const draggedElement = 'http://arkamcity.com/#!/item/11/summary';
|
||||
const droppable = document.createElement('a');
|
||||
droppable.setAttribute('id', 1);
|
||||
droppable.classList.add('vn-tr');
|
||||
const $event = {
|
||||
dataTransfer: {
|
||||
getData: () => draggedElement
|
||||
},
|
||||
target: droppable
|
||||
};
|
||||
controller.onDrop($event);
|
||||
|
||||
expect(controller.vnApp.showError).toHaveBeenCalledWith('Ticket not found');
|
||||
});
|
||||
});
|
||||
|
||||
describe('insert()', () => {
|
||||
it('should make a HTTP patch query and then call both refresh and showSuccess methods', () => {
|
||||
jest.spyOn(controller.$.model, 'refresh').mockReturnThis();
|
||||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
const routeId = 1;
|
||||
const ticketId = 11;
|
||||
const data = {ticketId};
|
||||
$httpBackend.expect('PATCH', `Routes/1/insertTicket`, data).respond();
|
||||
controller.insert(routeId, ticketId);
|
||||
$httpBackend.flush();
|
||||
|
||||
expect(controller.vnApp.showSuccess).toHaveBeenCalled();
|
||||
expect(controller.$.model.refresh).toHaveBeenCalledWith();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -161,11 +161,11 @@ class Controller extends Section {
|
|||
this.insert(ticketId);
|
||||
}
|
||||
|
||||
insert(id) {
|
||||
const params = {routeId: this.route.id};
|
||||
const query = `Routes/${id}/ticketToRoute`;
|
||||
insert(ticketId) {
|
||||
ticketId = parseInt(ticketId);
|
||||
|
||||
return this.$http.patch(query, params).then(() => {
|
||||
const query = `Routes/${this.route.id}/insertTicket`;
|
||||
return this.$http.patch(query, {ticketId}).then(() => {
|
||||
this.vnApp.showSuccess(this.$t('Data saved!'));
|
||||
this.$.model.refresh();
|
||||
this.card.reload();
|
||||
|
|
|
@ -309,8 +309,8 @@ describe('Route', () => {
|
|||
jest.spyOn(controller.vnApp, 'showSuccess');
|
||||
|
||||
const ticketId = 11;
|
||||
const data = {routeId: 1};
|
||||
$httpBackend.expect('PATCH', `Routes/11/ticketToRoute`, data).respond();
|
||||
const data = {ticketId};
|
||||
$httpBackend.expect('PATCH', `Routes/1/insertTicket`, data).respond();
|
||||
controller.insert(ticketId);
|
||||
$httpBackend.flush();
|
||||
|
||||
|
|
Loading…
Reference in New Issue