diff --git a/db/dump/fixtures.sql b/db/dump/fixtures.sql
index 619e5ae2c..7d2da8658 100644
--- a/db/dump/fixtures.sql
+++ b/db/dump/fixtures.sql
@@ -351,16 +351,6 @@ INSERT INTO `vn`.`creditInsurance`(`id`, `creditClassification`, `credit`, `crea
(2, 2, 6000, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), NULL),
(3, 3, 10000, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), NULL);
-INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`)
- VALUES
- (1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 7, 'first route', 2.7, 10, CURDATE(), CURDATE()),
- (2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 7, 'second route', 0.9, 20, CURDATE(), CURDATE()),
- (3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 7, 'third route', 1.1, 30, CURDATE(), CURDATE()),
- (4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 7, 'fourth route', 0.1, 40, CURDATE(), CURDATE()),
- (5, '1899-12-30 16:00:00', 56, CURDATE(), 4, 8, 'fifth route', NULL, 50, CURDATE(), CURDATE()),
- (6, NULL, 57, CURDATE(), 5, 8, 'sixth route', NULL, 60, CURDATE(), CURDATE()),
- (7, NULL, 57, CURDATE(), 6, NULL, 'seventh route', NULL, 70, CURDATE(), CURDATE());
-
INSERT INTO `vn2008`.`empresa_grupo`(`empresa_grupo_id`, `grupo`)
VALUES
(1, 'Wayne Industries');
@@ -456,32 +446,42 @@ INSERT INTO `vn`.`zone` (`id`, `name`, `hour`, `warehouseFk`, `agencyModeFk`, `t
(12, 'Zone entanglement', CONCAT(CURRENT_DATE(), ' ', TIME('22:00')), 4, 4, 0, 0, 0),
(13, 'Zone quantum break', CONCAT(CURRENT_DATE(), ' ', TIME('22:00')), 5, 5, 0, 0, 0);
+INSERT INTO `vn`.`route`(`id`, `time`, `workerFk`, `created`, `vehicleFk`, `agencyModeFk`, `description`, `m3`, `cost`, `started`, `finished`, `zoneFk`)
+ VALUES
+ (1, '1899-12-30 12:15:00', 56, CURDATE(), 1, 1, 'first route', 1.8, 10, CURDATE(), CURDATE(), 1),
+ (2, '1899-12-30 13:20:00', 56, CURDATE(), 1, 2, 'second route', 0.2, 20, CURDATE(), CURDATE(), 9),
+ (3, '1899-12-30 14:30:00', 56, CURDATE(), 2, 3, 'third route', 0.5, 30, CURDATE(), CURDATE(), 10),
+ (4, '1899-12-30 15:45:00', 56, CURDATE(), 3, 4, 'fourth route', 0, 40, CURDATE(), CURDATE(), 12),
+ (5, '1899-12-30 16:00:00', 56, CURDATE(), 4, 5, 'fifth route', 0.1, 50, CURDATE(), CURDATE(), 13),
+ (6, NULL, 57, CURDATE(), 5, 7, 'sixth route', 1.7, 60, CURDATE(), CURDATE(), 3),
+ (7, NULL, 57, CURDATE(), 6, 8, 'seventh route', 0, 70, CURDATE(), CURDATE(), 5);
+
INSERT INTO `vn`.`ticket`(`id`, `priority`, `agencyModeFk`,`warehouseFk`,`routeFk`, `shipped`, `landed`, `clientFk`,`nickname`, `addressFk`, `refFk`, `isDeleted`, `zoneFk`, `created`)
VALUES
- (1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
- (2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
- (3 , 1, 7, 1, 1, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, 3, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
- (4 , 3, 2, 1, 1, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, 9, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
- (5 , 3, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, 10, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
- (6 , 1, 3, 3, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
- (7 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, 3, CURDATE()),
- (8 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Bat cave', 121, NULL, 0, 3, CURDATE()),
- (9 , NULL, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Stark tower', 124, NULL, 0, 3, CURDATE()),
- (10, 1, 1, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, 11, CURDATE()),
- (11, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, CURDATE()),
- (12, 1, 1, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()),
- (13, 1, 7, 1, 2, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()),
- (14, 1, 2, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()),
- (15, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, 3, CURDATE()),
- (16, 1, 7, 1, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
- (17, 1, 7, 2, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
- (18, 1, 4, 4, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()),
- (19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
- (20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
- (21, NULL, 5, 5, NULL, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
- (22, NULL, 5, 5, NULL, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
- (23, NULL, 10, 1, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'address 21', 121, NULL, 0, 8, CURDATE()),
- (24 ,NULL, 10, 1, NULL, CURDATE(), CURDATE(), 101, 'Bruce Wayne', 1, NULL, 0, 8, CURDATE());
+ (1 , 3, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Bat cave', 121, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
+ (2 , 1, 1, 1, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T1111111', 0, 1, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
+ (3 , 1, 7, 1, 6, DATE_ADD(CURDATE(), INTERVAL -2 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -2 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T2222222', 0, 3, DATE_ADD(CURDATE(), INTERVAL -2 MONTH)),
+ (4 , 3, 2, 1, 2, DATE_ADD(CURDATE(), INTERVAL -3 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -3 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T3333333', 0, 9, DATE_ADD(CURDATE(), INTERVAL -3 MONTH)),
+ (5 , 3, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -4 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -4 MONTH), INTERVAL +1 DAY), 104, 'Stark tower', 124, 'T4444444', 0, 10, DATE_ADD(CURDATE(), INTERVAL -4 MONTH)),
+ (6 , 1, 3, 3, 3, DATE_ADD(CURDATE(), INTERVAL -1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL -1 MONTH), INTERVAL +1 DAY), 101, 'Mountain Drive Gotham', 1, 'A1111111', 0, 10, DATE_ADD(CURDATE(), INTERVAL -1 MONTH)),
+ (7 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Mountain Drive Gotham', 1, NULL, 0, 3, CURDATE()),
+ (8 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'Bat cave', 121, NULL, 0, 3, CURDATE()),
+ (9 , NULL, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Stark tower', 124, NULL, 0, 3, CURDATE()),
+ (10, 1, 1, 5, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'Ingram Street', 2, NULL, 0, 1, CURDATE()),
+ (11, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 102, 'NY roofs', 122, NULL, 0, 3, CURDATE()),
+ (12, 1, 1, 1, 1, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 1, CURDATE()),
+ (13, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 103, 'Phone Box', 123, NULL, 0, 3, CURDATE()),
+ (14, 1, 2, 1, NULL, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 104, 'Malibu Point', 4, NULL, 0, 9, CURDATE()),
+ (15, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 105, 'Plastic Cell', 125, NULL, 0, 3, CURDATE()),
+ (16, 1, 7, 1, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
+ (17, 1, 7, 2, 6, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 106, 'Many Places', 126, NULL, 0, 3, CURDATE()),
+ (18, 1, 4, 4, 4, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 108, 'Cerebro', 128, NULL, 0, 12, CURDATE()),
+ (19, 1, 5, 5, 3, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 1, 13, CURDATE()),
+ (20, 1, 5, 5, 3, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Thailand', 129, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
+ (21, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Holland', 102, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
+ (22, NULL, 5, 5, 5, DATE_ADD(CURDATE(), INTERVAL +1 MONTH), DATE_ADD(DATE_ADD(CURDATE(),INTERVAL +1 MONTH), INTERVAL +1 DAY), 109, 'Somewhere in Japan', 103, NULL, 0, 13, DATE_ADD(CURDATE(), INTERVAL +1 MONTH)),
+ (23, NULL, 8, 1, 7, CURDATE(), DATE_ADD(CURDATE(), INTERVAL + 1 DAY), 101, 'address 21', 121, NULL, 0, 5, CURDATE()),
+ (24 ,NULL, 8, 1, 7, CURDATE(), CURDATE(), 101, 'Bruce Wayne', 1, NULL, 0, 5, CURDATE());
INSERT INTO `vn`.`ticketObservation`(`id`, `ticketFk`, `observationTypeFk`, `description`)
VALUES
diff --git a/e2e/paths/03-worker-module/02_time_control.spec.js b/e2e/paths/03-worker-module/02_time_control.spec.js
index 42be3e9e0..be48b13dd 100644
--- a/e2e/paths/03-worker-module/02_time_control.spec.js
+++ b/e2e/paths/03-worker-module/02_time_control.spec.js
@@ -358,7 +358,7 @@ describe('Worker time control path', () => {
it(`should check Hank Pym doesn't have hours set on the next months first week`, async() => {
const wholeWeekHours = await nightmare
.waitToClick(selectors.workerTimeControl.nextMonthButton)
- .waitToClick(selectors.workerTimeControl.nextMonthButton)
+ .waitForTextInElement(selectors.workerTimeControl.weekWorkedHours, '00:00 Hours')
.waitToGetProperty(selectors.workerTimeControl.weekWorkedHours, 'innerText');
expect(wholeWeekHours).toEqual('00:00 Hours');
diff --git a/e2e/paths/05-ticket-module/06_basic_data_steps.spec.js b/e2e/paths/05-ticket-module/06_basic_data_steps.spec.js
index 0f02c6af7..3dcac0765 100644
--- a/e2e/paths/05-ticket-module/06_basic_data_steps.spec.js
+++ b/e2e/paths/05-ticket-module/06_basic_data_steps.spec.js
@@ -30,6 +30,7 @@ describe('Ticket Edit basic data path', () => {
it(`should confirm the zone autocomplete is enabled for the role productionBoss`, async() => {
const disabled = await nightmare
+ .waitForSpinnerLoad()
.wait(selectors.ticketBasicData.zoneAutocomplete)
.evaluate(selector => {
return document.querySelector(selector).disabled;
diff --git a/front/core/components/treeview/child.html b/front/core/components/treeview/child.html
new file mode 100644
index 000000000..1b928d5ea
--- /dev/null
+++ b/front/core/components/treeview/child.html
@@ -0,0 +1,20 @@
+
+
+
+
+
+
diff --git a/front/core/components/treeview/content.js b/front/core/components/treeview/child.js
similarity index 51%
rename from front/core/components/treeview/content.js
rename to front/core/components/treeview/child.js
index 506117d4f..9e4edef35 100644
--- a/front/core/components/treeview/content.js
+++ b/front/core/components/treeview/child.js
@@ -2,22 +2,33 @@ import ngModule from '../../module';
class Controller {
constructor($element, $scope, $compile) {
- this.$element = $element;
this.$scope = $scope;
this.$compile = $compile;
+ this.element = $element[0];
+
+ this.element.$ctrl = this;
+ this.element.droppable = true;
+ this.dropCount = 0;
+ this.element.classList.add('vn-droppable');
}
$onInit() {
+ const transcludeElement = this.element.querySelector('.content');
+ const content = angular.element(transcludeElement);
+
if (this.item.parent) {
this.treeview.$transclude(($clone, $scope) => {
this.$contentScope = $scope;
$scope.item = this.item;
- this.$element.append($clone);
+ content.append($clone);
});
+
+ this.element.draggable = true;
+ this.element.classList.add('vn-draggable');
} else {
let template = `{{$ctrl.treeview.rootLabel}}`;
let $clone = this.$compile(template)(this.$scope);
- this.$element.append($clone);
+ content.append($clone);
}
}
@@ -25,10 +36,21 @@ class Controller {
if (this.$contentScope)
this.$contentScope.$destroy();
}
+
+ dragEnter() {
+ this.dropCount++;
+
+ if (element != this.dropping) {
+ this.undrop();
+ if (element) element.classList.add('dropping');
+ this.dropping = element;
+ }
+ }
}
Controller.$inject = ['$element', '$scope', '$compile'];
-ngModule.component('vnTreeviewContent', {
+ngModule.component('vnTreeviewChild', {
+ template: require('./child.html'),
controller: Controller,
bindings: {
item: '<'
diff --git a/front/core/components/treeview/childs.html b/front/core/components/treeview/childs.html
index 2dd7e77ef..de69ffb89 100644
--- a/front/core/components/treeview/childs.html
+++ b/front/core/components/treeview/childs.html
@@ -1,34 +1,11 @@
- -
-
-
-
-
-
-
-
+ -
+
+
+ items="item.childs">
\ No newline at end of file
diff --git a/front/core/components/treeview/childs.js b/front/core/components/treeview/childs.js
index a9bd42077..d94c88df9 100644
--- a/front/core/components/treeview/childs.js
+++ b/front/core/components/treeview/childs.js
@@ -7,10 +7,6 @@ class Controller extends Component {
event.preventDefault();
this.treeview.onToggle(item);
}
-
- onDrop(item, dragged, dropped) {
- this.treeview.onDrop(item, dragged, dropped);
- }
}
ngModule.component('vnTreeviewChilds', {
diff --git a/front/core/components/treeview/index.js b/front/core/components/treeview/index.js
index d9da39215..728ea182e 100644
--- a/front/core/components/treeview/index.js
+++ b/front/core/components/treeview/index.js
@@ -1,18 +1,110 @@
import ngModule from '../../module';
import Component from '../../lib/component';
import './style.scss';
-
import './childs';
-import './content';
+import './child';
/**
* Treeview
*/
export default class Treeview extends Component {
- constructor($element, $scope, $transclude) {
+ constructor($element, $scope, $transclude, $window) {
super($element, $scope);
this.$transclude = $transclude;
+ this.$window = $window;
this.readOnly = true;
+
+ this.element.addEventListener('dragstart',
+ event => this.dragStart(event));
+ this.element.addEventListener('dragend',
+ event => this.dragEnd(event));
+
+ this.element.addEventListener('dragover',
+ event => this.dragOver(event));
+ this.element.addEventListener('drop',
+ event => this.drop(event));
+ this.element.addEventListener('dragenter',
+ event => this.dragEnter(event));
+ this.element.addEventListener('dragleave',
+ event => this.dragLeave(event));
+
+ this.dropCount = 0;
+ }
+
+ undrop() {
+ if (!this.dropping) return;
+ this.dropping.classList.remove('dropping');
+ this.dropping = null;
+ }
+
+ findDroppable(event) {
+ let element = event.target;
+ while (element != this.element && !element.droppable)
+ element = element.parentNode;
+ if (element == this.element)
+ return null;
+ return element;
+ }
+
+ dragOver(event) {
+ this.dragClientY = event.clientY;
+
+ // Prevents page reload
+ event.preventDefault();
+ }
+
+ onDragInterval() {
+ if (this.dragClientY > 0 && this.dragClientY < 75)
+ this.$window.scrollTo(0, this.$window.scrollY - 25);
+ }
+
+ dragStart(event) {
+ event.target.classList.add('dragging');
+ event.dataTransfer.setData('text', event.target.id);
+
+ const element = this.findDroppable(event);
+ this.dragging = element;
+
+ this.interval = setInterval(() => this.onDragInterval(), 100);
+ }
+
+ dragEnd(event) {
+ event.target.classList.remove('dragging');
+ this.undrop();
+ this.dropCount = 0;
+ this.dragging = null;
+ clearInterval(this.interval);
+ }
+
+ dragEnter(event) {
+ let element = this.findDroppable(event);
+ if (element) this.dropCount++;
+
+ if (element != this.dropping) {
+ this.undrop();
+ if (element) element.classList.add('dropping');
+ this.dropping = element;
+ }
+ }
+
+ dragLeave(event) {
+ let element = this.findDroppable(event);
+
+ if (element) {
+ this.dropCount--;
+ if (this.dropCount == 0) this.undrop();
+ }
+ }
+
+ drop(event) {
+ event.preventDefault();
+ this.element.classList.remove('dropping');
+
+ const $dropped = this.dropping.$ctrl.item;
+ const $dragged = this.dragging.$ctrl.item;
+
+ if ($dropped != $dragged.parent)
+ this.emit('drop', {$dropped, $dragged});
}
get data() {
@@ -109,7 +201,10 @@ export default class Treeview extends Component {
let childs = parent.childs;
if (!childs) childs = [];
- childs.push(item);
+ if (!parent.active)
+ this.unfold(parent);
+ else
+ childs.push(item);
if (this.sortFunc) {
childs = childs.sort((a, b) =>
@@ -120,12 +215,30 @@ export default class Treeview extends Component {
if (parent) parent.sons++;
}
- onDrop(item, dragged, dropped) {
- this.emit('drop', {item, dragged, dropped});
+ move(item, newParent) {
+ if (newParent == item) return;
+
+ if (item.parent) {
+ const parent = item.parent;
+ const childs = parent.childs;
+ const index = childs.indexOf(item);
+ parent.sons--;
+
+ childs.splice(index, 1);
+ }
+
+ item.parent = newParent;
+
+ if (!newParent.active) {
+ this.unfold(newParent).then(() => {
+ item.parent.sons++;
+ });
+ } else
+ this.create(item);
}
}
-Treeview.$inject = ['$element', '$scope', '$transclude'];
+Treeview.$inject = ['$element', '$scope', '$transclude', '$window'];
ngModule.component('vnTreeview', {
template: require('./index.html'),
diff --git a/front/core/components/treeview/index.spec.js b/front/core/components/treeview/index.spec.js
new file mode 100644
index 000000000..12cdc16e7
--- /dev/null
+++ b/front/core/components/treeview/index.spec.js
@@ -0,0 +1,260 @@
+describe('Component vnTreeview', () => {
+ let controller;
+ let $element;
+
+ beforeEach(angular.mock.module('vnCore', $translateProvider => {
+ $translateProvider.translations('en', {});
+ }));
+
+ beforeEach(inject(($compile, $rootScope) => {
+ $element = $compile(``)($rootScope);
+ controller = $element.controller('vnTreeview');
+
+ const promise = new Promise(() => {
+ return {name: 'My item'};
+ });
+
+ controller.fetchFunc = () => {
+ return promise;
+ };
+
+ controller.createFunc = () => {
+ return promise;
+ };
+
+ controller.removeFunc = () => {
+ return promise;
+ };
+
+ controller.sortFunc = () => {
+ return promise;
+ };
+ }));
+
+ afterEach(() => {
+ $element.remove();
+ });
+
+ // See how to test DOM element in Jest
+ xdescribe('undrop()', () => {
+ it(`should reset all drop events and properties`, () => {
+ controller.dropping = angular.element(``);
+ spyOn(controller.dropping.classList, 'remove');
+
+ controller.undrop();
+
+ expect(controller.dropping).toBeNull();
+ });
+ });
+
+ describe('dragOver()', () => {
+ it(`should set the dragClientY property`, () => {
+ const event = new Event('dragover');
+ event.clientY = 100;
+
+ controller.dragOver(event);
+
+ expect(controller.dragClientY).toEqual(100);
+ });
+ });
+
+ describe('data() setter', () => {
+ it(`should set the items property nested into a root element`, () => {
+ const items = [{name: 'Item1'}, {name: 'Item2'}];
+ controller.data = items;
+
+ const rootItem = controller.items[0];
+
+ expect(rootItem.childs).toEqual(items);
+ });
+ });
+
+ describe('fetch()', () => {
+ it(`should call the fetchFunc() method`, () => {
+ spyOn(controller, 'fetchFunc').and.returnValue(
+ new Promise(resolve => resolve([{name: 'My item'}]))
+ );
+ controller.fetch().then(() => {
+ expect(controller.data).toBeDefined();
+ });
+
+ expect(controller.fetchFunc).toHaveBeenCalledWith();
+ });
+ });
+
+ describe('setParent()', () => {
+ it(`should set the parent property recursively to each element of an item list`, () => {
+ spyOn(controller, 'setParent').and.callThrough();
+ const items = [{name: 'Item1'}, {name: 'Item2', childs: [
+ {name: 'Item3'}
+ ]}];
+ const rootItem = {name: 'Nested tree', sons: items};
+ controller.setParent(rootItem, items);
+
+ expect(items[0].parent).toEqual(rootItem);
+ expect(items[1].parent).toEqual(rootItem);
+ expect(controller.setParent).toHaveBeenCalledWith(rootItem, items[1].childs);
+ });
+ });
+
+ describe('onToggle()', () => {
+ it(`should call the fold() or unfold() methods`, () => {
+ spyOn(controller, 'fold');
+ spyOn(controller, 'unfold');
+
+ const item = {name: 'My item'};
+
+ controller.onToggle(item);
+ item.active = true;
+ controller.onToggle(item);
+
+ expect(controller.unfold).toHaveBeenCalledWith(item);
+ expect(controller.fold).toHaveBeenCalledWith(item);
+ });
+ });
+
+ describe('fold()', () => {
+ it(`should remove the childs and set the active property to false`, () => {
+ const item = {name: 'My item', childs: [{name: 'Item 1'}], active: true};
+
+ controller.fold(item);
+
+ expect(item.childs).toBeUndefined();
+ expect(item.active).toBeFalsy();
+ });
+ });
+
+ describe('unfold()', () => {
+ it(`should unfold a parent item`, () => {
+ const expectedResponse = [{name: 'Item 1'}, {name: 'Item 2'}];
+ spyOn(controller, 'fetchFunc').and.returnValue(
+ new Promise(resolve => resolve(expectedResponse))
+ );
+ spyOn(controller, 'setParent');
+ spyOn(controller, 'sortFunc');
+ const parent = {name: 'My item', sons: 1};
+ const child = {name: 'Item 1'};
+ child.parent = parent;
+ parent.childs = [child];
+
+ controller.unfold(parent).then(() => {
+ expect(controller.fetchFunc).toHaveBeenCalledWith({$item: parent});
+ expect(controller.setParent).toHaveBeenCalledWith(parent, expectedResponse);
+ expect(controller.sortFunc).toHaveBeenCalledWith(jasmine.any(Object));
+ expect(parent.active).toBeTruthy();
+ });
+ });
+ });
+
+ describe('onRemove()', () => {
+ it(`should call the removeFunc() method`, () => {
+ spyOn(controller, 'removeFunc');
+ const item = {name: 'My item'};
+ controller.onRemove(item);
+
+ expect(controller.removeFunc).toHaveBeenCalledWith({$item: item});
+ });
+ });
+
+ describe('remove()', () => {
+ it(`should remove a child element`, () => {
+ const parent = {name: 'My item', sons: 1};
+ const child = {name: 'Item 1'};
+ child.parent = parent;
+ parent.childs = [child];
+
+ controller.remove(child);
+
+ expect(parent.childs).toEqual([]);
+ expect(parent.sons).toEqual(0);
+ });
+ });
+
+ describe('onCreate()', () => {
+ it(`should call the createFunc() method`, () => {
+ spyOn(controller, 'createFunc');
+ const parent = {name: 'My item'};
+ controller.onCreate(parent);
+
+ expect(controller.createFunc).toHaveBeenCalledWith({$parent: parent});
+ });
+ });
+
+ describe('create()', () => {
+ it(`should unfold an inactive parent and then create a child`, () => {
+ spyOn(controller, 'unfold');
+ spyOn(controller, 'sortFunc');
+ const parent = {name: 'My item', sons: 2, childs: [
+ {name: 'Item 1'},
+ {name: 'Item 2'}
+ ]};
+ const child = {name: 'Item 3'};
+ child.parent = parent;
+ parent.childs.push(child);
+
+ controller.create(child);
+
+ expect(parent.sons).toEqual(3);
+ expect(controller.unfold).toHaveBeenCalledWith(parent);
+ expect(controller.sortFunc).toHaveBeenCalledWith(jasmine.any(Object));
+ expect(controller.sortFunc).toHaveBeenCalledTimes(2);
+ });
+
+ it(`should create a child on an active parent`, () => {
+ spyOn(controller, 'unfold');
+ spyOn(controller, 'sortFunc');
+ const parent = {name: 'My item', sons: 2, childs: [
+ {name: 'Item 1'},
+ {name: 'Item 2'}
+ ], active: true};
+ const child = {name: 'Item 3'};
+ child.parent = parent;
+
+ controller.create(child);
+
+ expect(parent.sons).toEqual(3);
+ expect(controller.unfold).not.toHaveBeenCalledWith(parent);
+ expect(controller.sortFunc).toHaveBeenCalledWith(jasmine.any(Object));
+ expect(controller.sortFunc).toHaveBeenCalledTimes(2);
+ });
+ });
+
+ describe('move()', () => {
+ it(`should move an item to anocher parent and then unfold the parent`, () => {
+ spyOn(controller, 'unfold').and.returnValue(
+ new Promise(resolve => resolve())
+ );
+ const newParent = {name: 'My item 2', sons: 0};
+ const parent = {name: 'My item', sons: 3, childs: [
+ {name: 'Item 1'},
+ {name: 'Item 2'}
+ ]};
+ const child = {name: 'Item 3'};
+ child.parent = parent;
+ parent.childs.push(child);
+
+ controller.move(child, newParent);
+
+ expect(parent.sons).toEqual(2);
+ expect(controller.unfold).toHaveBeenCalledWith(newParent);
+ });
+
+ it(`should move an item to anocher parent`, () => {
+ spyOn(controller, 'unfold');
+ spyOn(controller, 'create');
+ const newParent = {name: 'My item 2', sons: 0, active: true};
+ const parent = {name: 'My item', sons: 3, childs: [
+ {name: 'Item 1'},
+ {name: 'Item 2'}
+ ]};
+ const child = {name: 'Item 3'};
+ child.parent = parent;
+ parent.childs.push(child);
+
+ controller.move(child, newParent);
+
+ expect(parent.sons).toEqual(2);
+ expect(controller.unfold).not.toHaveBeenCalledWith(newParent);
+ });
+ });
+});
diff --git a/front/core/components/treeview/style.scss b/front/core/components/treeview/style.scss
index b3724a9f1..bd6175021 100644
--- a/front/core/components/treeview/style.scss
+++ b/front/core/components/treeview/style.scss
@@ -10,22 +10,6 @@ vn-treeview-childs {
li {
list-style: none;
- & > .node {
- @extend %clickable;
- display: flex;
- padding: 5px;
- align-items: center;
- }
-
- & > div > .arrow {
- min-width: 24px;
- margin-right: 10px;
- transition: transform 200ms;
- }
-
- & > div.expanded > .arrow {
- transform: rotate(180deg);
- }
ul {
padding-left: 2.2em;
}
@@ -45,8 +29,28 @@ vn-treeview-childs {
.node:hover > .buttons {
display: block
}
+
+ .content {
+ flex-grow: 1
+ }
}
-vn-treeview-content {
- flex-grow: 1
-}
\ No newline at end of file
+vn-treeview-child {
+ font-size: 16px;
+ display: block;
+
+ .node {
+ @extend %clickable;
+ display: flex;
+ padding: 5px;
+ align-items: center;
+ }
+ & > div > .arrow {
+ min-width: 24px;
+ margin-right: 10px;
+ transition: transform 200ms;
+ }
+ &.expanded > div > .arrow {
+ transform: rotate(180deg);
+ }
+}
\ No newline at end of file
diff --git a/front/core/directives/draggable.js b/front/core/directives/draggable.js
deleted file mode 100644
index 3b68a6cb6..000000000
--- a/front/core/directives/draggable.js
+++ /dev/null
@@ -1,43 +0,0 @@
-import ngModule from '../module';
-
-/**
- * Enables a draggable element and his drag events
- *
- * @return {Object} The directive
- */
-export function directive() {
- return {
- restrict: 'A',
- link: function($scope, $element, $attrs) {
- const element = $element[0];
- const isDraggable = $attrs.vnDraggable === 'true';
-
- if (!isDraggable) return;
-
- // Set draggable style properties
- element.style.cursor = 'move';
-
-
- // Enable as draggable element
- element.setAttribute('draggable', true);
-
- /**
- * Fires when a drag event starts
- */
- element.addEventListener('dragstart', event => {
- element.style.opacity = 0.5;
- event.stopPropagation();
- });
-
- /**
- * Fires when a drag event ends
- */
- element.addEventListener('dragend', event => {
- element.style.opacity = 1;
- event.stopPropagation();
- });
- }
- };
-}
-
-ngModule.directive('vnDraggable', directive);
diff --git a/front/core/directives/droppable.js b/front/core/directives/droppable.js
index 483282418..929b64be7 100644
--- a/front/core/directives/droppable.js
+++ b/front/core/directives/droppable.js
@@ -1,68 +1,43 @@
import ngModule from '../module';
import './droppable.scss';
-export function directive($parse) {
- return {
- restrict: 'A',
- link: function($scope, $element, $attrs) {
- const element = $element[0];
- const onDropEvent = $parse($attrs.onDrop);
- const isDroppable = $attrs.vnDroppable === 'true';
+class Controller {
+ constructor($element, $, $attrs) {
+ this.element = $element[0];
+ this.$ = $;
+ this.$attrs = $attrs;
- if (!isDroppable) return;
+ this.element.addEventListener('dragover',
+ event => event.preventDefault()); // Prevents page reload
+ this.element.addEventListener('drop',
+ event => this.drop(event));
+ this.element.addEventListener('dragenter',
+ event => this.dragEnter(event));
+ this.element.addEventListener('dragleave',
+ event => this.dragLeave(event));
+ }
- /**
- * Captures current dragging element
- */
- element.addEventListener('dragstart', () => {
- this.dragged = element;
- });
+ dragEnter(event) {
+ this.droppedElement = event.target;
+ this.element.classList.add('dropping');
+ }
- /**
- * Enter droppable area event
- */
- element.addEventListener('dragenter', event => {
- element.classList.add('active');
+ dragLeave(event) {
+ if (this.droppedElement === event.target)
+ this.element.classList.remove('dropping');
+ }
- event.stopImmediatePropagation();
- event.preventDefault();
- }, false);
-
-
- /**
- * Exit droppable area event
- */
- element.addEventListener('dragleave', event => {
- element.classList.remove('active');
-
- event.stopImmediatePropagation();
- event.preventDefault();
- });
-
- /**
- * Prevent dragover for allowing
- * dispatch drop event
- */
- element.addEventListener('dragover', event => {
- event.stopPropagation();
- event.preventDefault();
- });
-
- /**
- * Fires when a drop events
- */
- element.addEventListener('drop', event => {
- element.classList.remove('active');
-
- onDropEvent($scope, {event});
-
- event.stopPropagation();
- event.preventDefault();
- });
- }
- };
+ drop(event) {
+ if (event.defaultPrevented) return;
+ event.preventDefault();
+ this.element.classList.remove('dropping');
+ this.$.$eval(this.$attrs.vnDroppable, {$event: event});
+ }
}
+Controller.$inject = ['$element', '$scope', '$attrs'];
-directive.$inject = ['$parse'];
-
-ngModule.directive('vnDroppable', directive);
+ngModule.directive('vnDroppable', () => {
+ return {
+ controller: Controller
+ };
+});
diff --git a/front/core/directives/droppable.scss b/front/core/directives/droppable.scss
index 749bc9a12..97e6f8a19 100644
--- a/front/core/directives/droppable.scss
+++ b/front/core/directives/droppable.scss
@@ -1,11 +1,25 @@
@import "./variables";
+
+.vn-droppable,
+.vn-draggable,
[vn-droppable] {
border: 2px dashed transparent;
+ border-radius: 0.5em;
transition: all 0.5s;
+}
- &.active {
+.vn-droppable,
+[vn-droppable] {
+ display: block;
+
+ &.dropping {
background-color: $color-hover-cd;
- border: 2px dashed $color-bg-dark;
+ border-color: $color-bg-dark;
}
+}
+
+.vn-draggable.dragging {
+ background-color: $color-main-light;
+ border-color: $color-main;
}
\ No newline at end of file
diff --git a/front/core/directives/index.js b/front/core/directives/index.js
index 05f21b5cd..185046a3c 100644
--- a/front/core/directives/index.js
+++ b/front/core/directives/index.js
@@ -11,7 +11,6 @@ import './bind';
import './repeat-last';
import './title';
import './uvc';
-import './draggable';
import './droppable';
import './http-click';
import './http-submit';
diff --git a/front/core/lib/event-emitter.js b/front/core/lib/event-emitter.js
index 2dede42ab..022e4e98c 100644
--- a/front/core/lib/event-emitter.js
+++ b/front/core/lib/event-emitter.js
@@ -24,10 +24,12 @@ export default class EventEmitter {
*/
off(callback) {
if (!this.$events) return;
- for (let event in this.$events)
- for (let i = 0; i < event.length; i++)
+ for (let event in this.$events) {
+ for (let i = 0; i < event.length; i++) {
if (event[i].callback === callback)
event.splice(i--, 1);
+ }
+ }
}
/**
@@ -37,10 +39,12 @@ export default class EventEmitter {
*/
disconnect(thisArg) {
if (!this.$events) return;
- for (let event in this.$events)
- for (let i = 0; i < event.length; i++)
+ for (let event in this.$events) {
+ for (let i = 0; i < event.length; i++) {
if (event[i].thisArg === thisArg)
event.splice(i--, 1);
+ }
+ }
}
/**
@@ -72,9 +76,10 @@ export default class EventEmitter {
if (this[prop])
this[prop].disconnect(this);
this[prop] = value;
- if (value)
+ if (value) {
for (let event in handlers)
value.on(event, handlers[event], this);
+ }
}
}
}
diff --git a/loopback/locale/es.json b/loopback/locale/es.json
index 587d5e9c4..dffa15af6 100644
--- a/loopback/locale/es.json
+++ b/loopback/locale/es.json
@@ -109,6 +109,8 @@
"is invalid": "is invalid",
"The postcode doesn't exists. Ensure you put the correct format": "El código postal no existe. Asegúrate de ponerlo con el formato correcto",
"The department name can't be repeated": "El nombre del departamento no puede repetirse",
- "You can't create a claim for a removed ticket": "No puedes crear una reclamación para un ticket eliminado",
- "This phone already exists": "Este teléfono ya existe"
+ "This phone already exists": "Este teléfono ya existe",
+ "You cannot move a parent to any of its sons": "You cannot move a parent to any of its sons",
+ "You cannot move a parent to its own sons": "You cannot move a parent to its own sons",
+ "You can't create a claim for a removed ticket": "No puedes crear una reclamación para un ticket eliminado"
}
\ No newline at end of file
diff --git a/modules/agency/front/location/style.scss b/modules/agency/front/location/style.scss
index a3b237b13..d1597e460 100644
--- a/modules/agency/front/location/style.scss
+++ b/modules/agency/front/location/style.scss
@@ -1,14 +1,14 @@
@import "variables";
-vn-treeview-content {
- & > vn-check:not(.indeterminate) {
+vn-treeview-child {
+ .content > vn-check:not(.indeterminate) {
color: $color-main;
& > .btn {
border-color: $color-main;
}
}
- & > vn-check.checked {
+ .content > vn-check.checked {
color: $color-main;
}
}
\ No newline at end of file
diff --git a/modules/claim/front/action/index.html b/modules/claim/front/action/index.html
index 65467d349..d12399c55 100644
--- a/modules/claim/front/action/index.html
+++ b/modules/claim/front/action/index.html
@@ -1,121 +1,116 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
- Id
- Ticket
- Destination
- Landed
- Quantity
- Description
- Price
- Disc.
- Total
-
-
-
-
-
-
- {{saleClaimed.sale.itemFk | zeroFill:6}}
-
-
-
-
- {{::saleClaimed.sale.ticketFk}}
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Id
+ Ticket
+ Destination
+ Landed
+ Quantity
+ Description
+ Price
+ Disc.
+ Total
+
+
+
+
+
+
+ {{::saleClaimed.sale.itemFk | zeroFill:6}}
-
-
-
-
-
- {{saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}}
- {{saleClaimed.sale.quantity}}
- {{saleClaimed.sale.concept}}
- {{saleClaimed.sale.price | currency: 'EUR':2}}
- {{saleClaimed.sale.discount}} %
-
- {{saleClaimed.sale.quantity * saleClaimed.sale.price *
- ((100 - saleClaimed.sale.discount) / 100) | currency: 'EUR':2}}
-
-
-
-
-
-
-
-
-
-
+
+
+
+ {{::saleClaimed.sale.ticketFk}}
+
+
+
+
+
+
+ {{::saleClaimed.sale.ticket.landed | dateTime: 'dd/MM/yyyy'}}
+ {{::saleClaimed.sale.quantity}}
+ {{::saleClaimed.sale.concept}}
+ {{::saleClaimed.sale.price | currency: 'EUR':2}}
+ {{::saleClaimed.sale.discount}} %
+
+ {{saleClaimed.sale.quantity * saleClaimed.sale.price *
+ ((100 - saleClaimed.sale.discount) / 100) | currency: 'EUR':2}}
+
+
+
+
+
+
+
+
+
+
-
+
diff --git a/modules/claim/front/action/style.scss b/modules/claim/front/action/style.scss
index 3d54485e7..0124b716b 100644
--- a/modules/claim/front/action/style.scss
+++ b/modules/claim/front/action/style.scss
@@ -1,4 +1,19 @@
vn-claim-action {
+ .header {
+ display: flex;
+ justify-content: space-between;
+ align-items: center;
+ align-content: center;
+
+ vn-tool-bar {
+ flex: 1
+ }
+
+ vn-check {
+ flex: none;
+ }
+ }
+
vn-dialog[vn-id=addSales] {
tpl-body {
width: 950px;
diff --git a/modules/claim/front/dms/index/index.html b/modules/claim/front/dms/index/index.html
index 89d1e0b22..fcf5c4346 100644
--- a/modules/claim/front/dms/index/index.html
+++ b/modules/claim/front/dms/index/index.html
@@ -5,7 +5,7 @@
data="$ctrl.photos">
-
+
Drag & Drop files here...
diff --git a/modules/claim/front/dms/index/index.js b/modules/claim/front/dms/index/index.js
index 12d22bb2a..0aa48b7cc 100644
--- a/modules/claim/front/dms/index/index.js
+++ b/modules/claim/front/dms/index/index.js
@@ -36,8 +36,9 @@ class Controller {
}
}
- onDrop(event) {
- const files = event.dataTransfer.files;
+ onDrop($event) {
+ console.log($event);
+ const files = $event.dataTransfer.files;
this.setDefaultParams().then(() => {
this.dms.files = files;
this.create();
diff --git a/modules/route/back/methods/route/specs/filter.spec.js b/modules/route/back/methods/route/specs/filter.spec.js
index ba32c956c..a4742c128 100644
--- a/modules/route/back/methods/route/specs/filter.spec.js
+++ b/modules/route/back/methods/route/specs/filter.spec.js
@@ -117,6 +117,6 @@ describe('Route filter()', () => {
let result = await app.models.Route.filter(ctx);
- expect(result.length).toEqual(4);
+ expect(result.length).toEqual(1);
});
});
diff --git a/modules/route/back/methods/route/specs/getTickets.spec.js b/modules/route/back/methods/route/specs/getTickets.spec.js
index 3888156b6..15028309f 100644
--- a/modules/route/back/methods/route/specs/getTickets.spec.js
+++ b/modules/route/back/methods/route/specs/getTickets.spec.js
@@ -4,6 +4,6 @@ describe('route getTickets()', () => {
it('should return the tickets for a given route', async() => {
let result = await app.models.Route.getTickets(2);
- expect(result.length).toEqual(4);
+ expect(result.length).toEqual(1);
});
});
diff --git a/modules/route/back/methods/route/specs/guessPriority.spec.js b/modules/route/back/methods/route/specs/guessPriority.spec.js
index cc536787a..075ea05c8 100644
--- a/modules/route/back/methods/route/specs/guessPriority.spec.js
+++ b/modules/route/back/methods/route/specs/guessPriority.spec.js
@@ -1,7 +1,7 @@
const app = require('vn-loopback/server/server');
describe('route guessPriority()', () => {
- const targetRouteId = 2;
+ const targetRouteId = 7;
let routeTicketsToRestore;
afterAll(async done => {
@@ -17,25 +17,23 @@ describe('route guessPriority()', () => {
it('should confirm the tickets in the target route have no priority yet', async() => {
routeTicketsToRestore = await app.models.Ticket.find({where: {routeFk: targetRouteId}});
- expect(routeTicketsToRestore.length).toEqual(4);
+ expect(routeTicketsToRestore.length).toEqual(2);
+
+ expect(routeTicketsToRestore[0].id).toEqual(23);
expect(routeTicketsToRestore[0].priority).toBeNull();
- expect(routeTicketsToRestore[0].id).toEqual(7);
+ expect(routeTicketsToRestore[1].id).toEqual(24);
expect(routeTicketsToRestore[1].priority).toBeNull();
- expect(routeTicketsToRestore[1].id).toEqual(8);
- expect(routeTicketsToRestore[2].priority).toBeNull();
- expect(routeTicketsToRestore[2].id).toEqual(9);
});
it('should call guessPriority() and then check the tickets in the target route now have their priorities defined', async() => {
await app.models.Route.guessPriority(targetRouteId);
let routeTickets = await app.models.Ticket.find({where: {routeFk: targetRouteId}, fields: ['id', 'priority']});
- expect(routeTickets.length).toEqual(4);
- expect(routeTickets[0].priority).toEqual(1);
- expect(routeTickets[0].id).toEqual(7);
- expect(routeTickets[1].priority).toEqual(3);
- expect(routeTickets[1].id).toEqual(8);
- expect(routeTickets[2].priority).toEqual(2);
- expect(routeTickets[2].id).toEqual(9);
+ expect(routeTickets.length).toEqual(2);
+
+ expect(routeTickets[0].id).toEqual(23);
+ expect(routeTickets[0].priority).toEqual(3);
+ expect(routeTickets[1].id).toEqual(24);
+ expect(routeTickets[1].priority).toEqual(1);
});
});
diff --git a/modules/route/back/methods/route/specs/summary.spec.js b/modules/route/back/methods/route/specs/summary.spec.js
index 5b31ff19f..ba976ae94 100644
--- a/modules/route/back/methods/route/specs/summary.spec.js
+++ b/modules/route/back/methods/route/specs/summary.spec.js
@@ -11,7 +11,7 @@ describe('route summary()', () => {
const result = await app.models.Route.summary(1);
const agency = result.route.agencyMode();
- expect(agency.name).toEqual('Silla247');
+ expect(agency.name).toEqual('inhouse pickup');
});
it(`should return a summary object containing it's vehicle`, async() => {
@@ -31,6 +31,6 @@ describe('route summary()', () => {
it(`should return a summary object containing data from the tickets`, async() => {
const result = await app.models.Route.summary(2);
- expect(result.tickets.length).toEqual(4);
+ expect(result.tickets.length).toEqual(1);
});
});
diff --git a/modules/route/back/methods/route/specs/updateVolume.spec.js b/modules/route/back/methods/route/specs/updateVolume.spec.js
index 75ee3c139..a1ff67acc 100644
--- a/modules/route/back/methods/route/specs/updateVolume.spec.js
+++ b/modules/route/back/methods/route/specs/updateVolume.spec.js
@@ -10,8 +10,8 @@ describe('route updateVolume()', () => {
afterAll(async done => {
- await originalRoute.updateAttributes({m3: 2.7});
- await ticketToRestore.updateAttributes({routeFk: 2});
+ await originalRoute.updateAttributes({m3: 1.8});
+ await ticketToRestore.updateAttributes({routeFk: null});
await app.models.RouteLog.destroyById(logIdToDestroy);
done();
});
@@ -19,12 +19,12 @@ describe('route updateVolume()', () => {
it('should confirm the original volume of the route is the expected', async() => {
originalRoute = await app.models.Route.findById(routeId);
- expect(originalRoute.m3).toEqual(2.7);
+ expect(originalRoute.m3).toEqual(1.8);
});
it('should confirm the route volume is updated when a ticket is added', async() => {
- ticketToRestore = await app.models.Ticket.findById(8);
- let updatedTicket = await app.models.Ticket.findById(8);
+ ticketToRestore = await app.models.Ticket.findById(14);
+ let updatedTicket = await app.models.Ticket.findById(14);
await updatedTicket.updateAttributes({routeFk: routeId});
await app.models.Route.updateVolume(ctx, routeId);
@@ -36,8 +36,9 @@ describe('route updateVolume()', () => {
it('should confirm the change is logged', async() => {
let logs = await app.models.RouteLog.find({fields: ['id', 'newInstance']});
+
let m3Log = logs.filter(log => {
- return log.newInstance.m3 === 3.1;
+ return log.newInstance.m3 === 1.9;
});
logIdToDestroy = m3Log[0].id;
diff --git a/modules/ticket/front/services/index.spec.js b/modules/ticket/front/services/index.spec.js
index 97ce890d9..cf416f84d 100644
--- a/modules/ticket/front/services/index.spec.js
+++ b/modules/ticket/front/services/index.spec.js
@@ -1,6 +1,6 @@
import './index.js';
-fdescribe('Ticket component vnTicketService', () => {
+describe('Ticket component vnTicketService', () => {
let controller;
let $httpBackend;
let $httpParamSerializer;
diff --git a/modules/worker/back/methods/department/moveChild.js b/modules/worker/back/methods/department/moveChild.js
new file mode 100644
index 000000000..97206f198
--- /dev/null
+++ b/modules/worker/back/methods/department/moveChild.js
@@ -0,0 +1,42 @@
+const UserError = require('vn-loopback/util/user-error');
+
+module.exports = Self => {
+ Self.remoteMethod('moveChild', {
+ description: 'Changes the parent of a child department',
+ accessType: 'WRITE',
+ accepts: [{
+ arg: 'id',
+ type: 'Number',
+ description: 'The department id',
+ http: {source: 'path'}
+ }, {
+ arg: 'parentId',
+ type: 'Number',
+ description: 'New parent id',
+ }],
+ returns: {
+ type: 'Object',
+ root: true
+ },
+ http: {
+ path: `/:id/moveChild`,
+ verb: 'POST'
+ }
+ });
+
+ Self.moveChild = async(id, parentId = null) => {
+ const models = Self.app.models;
+ const child = await models.Department.findById(id);
+
+ if (id == parentId) return;
+
+ if (parentId) {
+ const parent = await models.Department.findById(parentId);
+
+ if (child.lft < parent.lft && child.rgt > parent.rgt)
+ throw new UserError('You cannot move a parent to its own sons');
+ }
+
+ return child.updateAttribute('parentFk', parentId);
+ };
+};
diff --git a/modules/worker/back/methods/department/specs/createChild.spec.js b/modules/worker/back/methods/department/specs/createChild.spec.js
new file mode 100644
index 000000000..305732f58
--- /dev/null
+++ b/modules/worker/back/methods/department/specs/createChild.spec.js
@@ -0,0 +1,18 @@
+const app = require('vn-loopback/server/server');
+
+describe('department createChild()', () => {
+ let createdChild;
+
+ afterAll(async done => {
+ await createdChild.destroy();
+ done();
+ });
+
+ it('should create a new child', async() => {
+ const parentId = null;
+ createdChild = await app.models.Department.createChild(parentId, 'My new department');
+
+ expect(createdChild.name).toEqual('My new department');
+ expect(createdChild.parentFk).toBeNull();
+ });
+});
diff --git a/modules/worker/back/methods/department/specs/moveChild.spec.js b/modules/worker/back/methods/department/specs/moveChild.spec.js
new file mode 100644
index 000000000..3358ebf77
--- /dev/null
+++ b/modules/worker/back/methods/department/specs/moveChild.spec.js
@@ -0,0 +1,23 @@
+const app = require('vn-loopback/server/server');
+
+describe('department moveChild()', () => {
+ let updatedChild;
+
+ afterAll(async done => {
+ const child = await app.models.Department.findById(updatedChild.id);
+ await child.updateAttribute('parentFk', null);
+ done();
+ });
+
+ it('should move a child department to a new parent', async() => {
+ const childId = 22;
+ const parentId = 1;
+
+ const child = await app.models.Department.findById(childId);
+
+ expect(child.parentFk).toBeNull();
+ updatedChild = await app.models.Department.moveChild(childId, parentId);
+
+ expect(updatedChild.parentFk).toEqual(1);
+ });
+});
diff --git a/modules/worker/back/methods/department/specs/removeChild.spec.js b/modules/worker/back/methods/department/specs/removeChild.spec.js
new file mode 100644
index 000000000..1fe3d10ef
--- /dev/null
+++ b/modules/worker/back/methods/department/specs/removeChild.spec.js
@@ -0,0 +1,21 @@
+const app = require('vn-loopback/server/server');
+
+describe('department removeChild()', () => {
+ let removedChild;
+
+ afterAll(async done => {
+ await app.models.Department.create(removedChild);
+ done();
+ });
+
+ it('should remove a child department', async() => {
+ const childId = 1;
+
+ removedChild = await app.models.Department.findById(childId);
+ const result = await app.models.Department.removeChild(childId);
+ const existsChild = await app.models.Department.findById(childId);
+
+ expect(result.count).toEqual(1);
+ expect(existsChild).toBeNull();
+ });
+});
diff --git a/modules/worker/back/models/department.js b/modules/worker/back/models/department.js
index e6905d273..5a927fc64 100644
--- a/modules/worker/back/models/department.js
+++ b/modules/worker/back/models/department.js
@@ -2,4 +2,5 @@ module.exports = Self => {
require('../methods/department/getLeaves')(Self);
require('../methods/department/createChild')(Self);
require('../methods/department/removeChild')(Self);
+ require('../methods/department/moveChild')(Self);
};
diff --git a/modules/worker/back/models/department.json b/modules/worker/back/models/department.json
index bb5d5e943..7de76e039 100644
--- a/modules/worker/back/models/department.json
+++ b/modules/worker/back/models/department.json
@@ -16,6 +16,15 @@
},
"parentFk": {
"type": "Number"
+ },
+ "lft": {
+ "type": "Number"
+ },
+ "rgt": {
+ "type": "Number"
+ },
+ "sons": {
+ "type": "Number"
}
}
}
diff --git a/modules/worker/front/department/index.html b/modules/worker/front/department/index.html
index 5093fe570..2abb81b04 100644
--- a/modules/worker/front/department/index.html
+++ b/modules/worker/front/department/index.html
@@ -10,7 +10,10 @@
fetch-func="$ctrl.onFetch($item)"
remove-func="$ctrl.onRemove($item)"
create-func="$ctrl.onCreate($parent)"
- sort-func="$ctrl.onSort($a, $b)">
+ sort-func="$ctrl.onSort($a, $b)"
+ on-drop="$ctrl.onDrop($dropped, $dragged)"
+ on-drag-start="$ctrl.onDragStart(item)"
+ on-drag-end="$ctrl.onDragEnd(item)">
{{::item.name}}
diff --git a/modules/worker/front/department/index.js b/modules/worker/front/department/index.js
index 1a72681bc..383fee74b 100644
--- a/modules/worker/front/department/index.js
+++ b/modules/worker/front/department/index.js
@@ -23,19 +23,13 @@ class Controller {
return a.name.localeCompare(b.name);
}
- /* onDrop(item, dragged, dropped) {
- if (dropped.scope.item) {
- const droppedItem = dropped.scope.item;
- const draggedItem = dragged.scope.item;
-
- if (droppedItem.childs)
- droppedItem.childs.push(Object.assign({}, draggedItem));
-
- dragged.element.remove();
-
- this.$scope.$apply();
- }
- } */
+ onDrop(dropped, dragged) {
+ const params = dropped ? {parentId: dropped.id} : null;
+ const query = `/api/departments/${dragged.id}/moveChild`;
+ this.$http.post(query, params).then(() => {
+ this.$.treeview.move(dragged, dropped);
+ });
+ }
onCreate(parent) {
this.newChild = {
@@ -62,12 +56,8 @@ class Controller {
if (parent && parent.id)
params.parentId = parent.id;
- if (!parent.active)
- this.$.treeview.unfold(parent);
-
const query = `/api/departments/createChild`;
this.$http.post(query, params).then(res => {
- const parent = this.newChild.parent;
const item = res.data;
item.parent = parent;