From 6b44686ff4a0419703a8a556c9fa979d51b820fe Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Fri, 4 Oct 2019 09:28:09 +0200 Subject: [PATCH 01/46] update zone and shipped on #1746 --- .../front/basic-data/step-one/index.html | 3 +- .../ticket/front/basic-data/step-one/index.js | 56 +++---- .../front/basic-data/step-one/index.spec.js | 157 +++++++++++++++++- 3 files changed, 179 insertions(+), 37 deletions(-) diff --git a/modules/ticket/front/basic-data/step-one/index.html b/modules/ticket/front/basic-data/step-one/index.html index 3d79b9b68..4e3cf361a 100644 --- a/modules/ticket/front/basic-data/step-one/index.html +++ b/modules/ticket/front/basic-data/step-one/index.html @@ -14,6 +14,7 @@ label="Client" show-field="name" value-field="id" + search-function="{or: [{id: $search}, {name: {like: '%'+ $search +'%'}}]}" field="$ctrl.clientId" initial-data="$ctrl.clientId" order="id"> @@ -23,7 +24,7 @@ label="Address" show-field="nickname" value-field="id" - field="$ctrl.ticket.addressFk" + field="$ctrl.addressId" order="isActive DESC"> {{::isActive ? '' : 'INACTIVE'}} {{::nickname}} diff --git a/modules/ticket/front/basic-data/step-one/index.js b/modules/ticket/front/basic-data/step-one/index.js index 862a7a315..09632ba5a 100644 --- a/modules/ticket/front/basic-data/step-one/index.js +++ b/modules/ticket/front/basic-data/step-one/index.js @@ -26,10 +26,7 @@ class Controller { } get clientId() { - if (this.ticket) - return this.ticket.clientFk; - - return null; + return this.ticket && this.ticket.clientFk; } set clientId(value) { @@ -39,11 +36,24 @@ class Controller { this.onChangeClient(value); } - get warehouseId() { - if (this.ticket) - return this.ticket.warehouseFk; + get addressId() { + return this.ticket && this.ticket.addressFk; + } - return null; + set addressId(value) { + if (value != this.ticket.addressFk) { + this.ticket.addressFk = value; + this.getShipped({ + landed: this.ticket.landed, + addressFk: value, + agencyModeFk: this.ticket.agencyModeFk, + warehouseFk: this.ticket.warehouseFk + }); + } + } + + get warehouseId() { + return this.ticket && this.ticket.warehouseFk; } set warehouseId(value) { @@ -60,10 +70,7 @@ class Controller { get shipped() { - if (this.ticket) - return this.ticket.shipped; - - return null; + return this.ticket && this.ticket.shipped; } set shipped(value) { @@ -77,10 +84,7 @@ class Controller { } get landed() { - if (this.ticket) - return this.ticket.landed; - - return null; + return this.ticket && this.ticket.landed; } set landed(value) { @@ -94,17 +98,14 @@ class Controller { } get agencyModeId() { - if (this.ticket) - return this.ticket.agencyModeFk; - - return null; + return this.ticket && this.ticket.agencyModeFk; } set agencyModeId(value) { if (value != this.ticket.agencyModeFk) { this.ticket.agencyModeFk = value; - this.getShipped({ - landed: this.ticket.landed, + this.getLanded({ + shipped: this.ticket.shipped, addressFk: this.ticket.addressFk, agencyModeFk: value, warehouseFk: this.ticket.warehouseFk @@ -113,10 +114,7 @@ class Controller { } get zoneId() { - if (this.ticket) - return this.ticket.zoneFk; - - return null; + return this.ticket && this.ticket.zoneFk; } set zoneId(value) { @@ -206,9 +204,10 @@ class Controller { this.$http.get(query, {params}).then(res => { if (res.data) { this.ticket.zoneFk = res.data.zoneFk; - this.ticket.landed = res.data.landed; this.ticket.agencyModeFk = res.data.agencyModeFk; this.ticket.warehouseFk = res.data.warehouseFk; + this.ticket.landed = res.data.landed; + this.ticket.shipped = params.shipped; } else { return this.vnApp.showError( this.$translate.instant(`No delivery zone available for this landing date`) @@ -226,9 +225,10 @@ class Controller { this.$http.get(query, {params}).then(res => { if (res.data) { this.ticket.zoneFk = res.data.zoneFk; - this.ticket.shipped = res.data.shipped; this.ticket.agencyModeFk = res.data.agencyModeFk; this.ticket.warehouseFk = res.data.warehouseFk; + this.ticket.landed = params.landed; + this.ticket.shipped = res.data.shipped; } else { return this.vnApp.showError( this.$translate.instant(`No delivery zone available for this landing date`) diff --git a/modules/ticket/front/basic-data/step-one/index.spec.js b/modules/ticket/front/basic-data/step-one/index.spec.js index c743ca911..89ca7f171 100644 --- a/modules/ticket/front/basic-data/step-one/index.spec.js +++ b/modules/ticket/front/basic-data/step-one/index.spec.js @@ -5,14 +5,16 @@ describe('Ticket', () => { let $state; let controller; let $httpBackend; + let $httpParamSerializer; beforeEach(angular.mock.module('ticket', $translateProvider => { $translateProvider.translations('en', {}); })); - beforeEach(angular.mock.inject(($componentController, _$state_, _$httpBackend_) => { + beforeEach(angular.mock.inject(($componentController, _$state_, _$httpBackend_, _$httpParamSerializer_) => { $state = _$state_; $httpBackend = _$httpBackend_; + $httpParamSerializer = _$httpParamSerializer_; controller = $componentController('vnTicketBasicDataStepOne', {$state}); controller.ticket = { addressFk: 121, @@ -37,6 +39,14 @@ describe('Ticket', () => { }); }); + describe('clientId() getter', () => { + it('should return the clientFk property', () => { + controller.ticket = {id: 1, clientFk: 102}; + + expect(controller.clientId).toEqual(102); + }); + }); + describe('clientId() setter', () => { it('should set clientId property and call onChangeClient() method ', () => { spyOn(controller, 'onChangeClient'); @@ -47,6 +57,69 @@ describe('Ticket', () => { }); }); + describe('adressId() getter', () => { + it('should return the addressFk property', () => { + controller.ticket = {id: 1, addressFk: 99}; + + expect(controller.addressId).toEqual(99); + }); + }); + + describe('addressId() setter', () => { + it('should set addressId property and call getShipped() method ', () => { + spyOn(controller, 'getShipped'); + controller.ticket.addressFk = 99; + controller.addressId = 100; + const landed = new Date(); + const spectedResult = { + landed: landed, + addressFk: 100, + agencyModeFk: 7, + warehouseFk: 1 + }; + controller.landed = landed; + + expect(controller.getShipped).toHaveBeenCalledWith(spectedResult); + expect(controller.ticket.addressFk).toEqual(100); + }); + }); + + describe('warehouseId() getter', () => { + it('should return the warehouseId property', () => { + controller.ticket.warehouseFk = 2; + + expect(controller.warehouseId).toEqual(2); + }); + }); + + describe('warehouseId() setter', () => { + it('should set warehouseId property and call getShipped() method ', () => { + spyOn(controller, 'getShipped'); + controller.ticket.warehouseId = 1; + controller.warehouseId = 2; + const landed = new Date(); + const spectedResult = { + landed: landed, + addressFk: 121, + agencyModeFk: 7, + warehouseFk: 2 + }; + controller.landed = landed; + + expect(controller.getShipped).toHaveBeenCalledWith(spectedResult); + expect(controller.ticket.warehouseFk).toEqual(2); + }); + }); + + describe('shipped() getter', () => { + it('should return the shipped property', () => { + const shipped = new Date(); + controller.ticket.shipped = shipped; + + expect(controller.shipped).toEqual(shipped); + }); + }); + describe('shipped() setter', () => { it('should set shipped property and call getLanded() method ', () => { spyOn(controller, 'getLanded'); @@ -59,11 +132,19 @@ describe('Ticket', () => { }; controller.shipped = shipped; - expect(controller.getLanded).toHaveBeenCalledWith(spectedResult); }); }); + describe('landed() getter', () => { + it('should return the landed property', () => { + const landed = new Date(); + controller.ticket.landed = landed; + + expect(controller.landed).toEqual(landed); + }); + }); + describe('landed() setter', () => { it('should set shipped property and call getShipped() method ', () => { spyOn(controller, 'getShipped'); @@ -81,21 +162,29 @@ describe('Ticket', () => { }); }); + describe('agencyModeId() getter', () => { + it('should return the agencyModeFk property', () => { + controller.ticket.agencyModeFk = 66; + + expect(controller.agencyModeId).toEqual(66); + }); + }); + describe('agencyModeId() setter', () => { - it('should set agencyModeId property and call onChangeAgencyMode() method', () => { - spyOn(controller, 'getShipped'); - const landed = new Date(); + it('should set agencyModeId property and call getLanded() method', () => { + spyOn(controller, 'getLanded'); + const shipped = new Date(); const agencyModeId = 8; const spectedResult = { - landed: landed, + shipped: shipped, addressFk: 121, agencyModeFk: agencyModeId, warehouseFk: 1 }; - controller.ticket.landed = landed; + controller.ticket.shipped = shipped; controller.agencyModeId = 8; - expect(controller.getShipped).toHaveBeenCalledWith(spectedResult); + expect(controller.getLanded).toHaveBeenCalledWith(spectedResult); }); it('should do nothing if attempting to set the same agencyMode id', () => { @@ -115,6 +204,14 @@ describe('Ticket', () => { }); }); + describe('zoneId() getter', () => { + it('should return the zoneFk property', () => { + controller.ticket.zoneFk = 10; + + expect(controller.zoneId).toEqual(10); + }); + }); + describe('zoneId() setter', () => { it('should set zoneId property and call onChangeZone() method ', () => { const zoneId = 5; @@ -223,5 +320,49 @@ describe('Ticket', () => { $httpBackend.flush(); }); }); + + describe('getLanded()', () => { + it('should return an available landed date', async() => { + const shipped = new Date(); + const expectedResult = {landed: new Date()}; + const params = { + shipped: shipped, + addressFk: 121, + agencyModeFk: 7, + warehouseFk: 1 + }; + const serializedParams = $httpParamSerializer(params); + + $httpBackend.when('GET', `/api/Agencies/getLanded?${serializedParams}`).respond(200, expectedResult); + $httpBackend.expect('GET', `/api/Agencies/getLanded?${serializedParams}`); + controller.getLanded(params); + $httpBackend.flush(); + + expect(controller.shipped).toEqual(shipped); + expect(controller.landed).toEqual(expectedResult.landed); + }); + }); + + describe('getShipped()', () => { + it('should return an available shipped date', async() => { + const landed = new Date(); + const expectedResult = {shipped: new Date()}; + const params = { + landed: landed, + addressFk: 121, + agencyModeFk: 7, + warehouseFk: 1 + }; + const serializedParams = $httpParamSerializer(params); + + $httpBackend.when('GET', `/api/Agencies/getShipped?${serializedParams}`).respond(200, expectedResult); + $httpBackend.expect('GET', `/api/Agencies/getShipped?${serializedParams}`); + controller.getShipped(params); + $httpBackend.flush(); + + expect(controller.shipped).toEqual(expectedResult.shipped); + expect(controller.landed).toEqual(landed); + }); + }); }); }); From 9c3e7f50ec4e7063605a1369271a1186c0a8c8ad Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Fri, 4 Oct 2019 11:18:07 +0200 Subject: [PATCH 02/46] disabled autoload on stowaway model #1747 --- modules/ticket/front/descriptor/addStowaway.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/front/descriptor/addStowaway.html b/modules/ticket/front/descriptor/addStowaway.html index 74554d2be..3efaedc8d 100644 --- a/modules/ticket/front/descriptor/addStowaway.html +++ b/modules/ticket/front/descriptor/addStowaway.html @@ -12,7 +12,7 @@
Stowaways to add
- + Ticket id From 05aa9151eb661966baccc3438c1dd15fe6e2e191 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 8 Oct 2019 11:41:17 +0200 Subject: [PATCH 03/46] fixed stowaway list --- modules/ticket/front/descriptor/addStowaway.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/front/descriptor/addStowaway.html b/modules/ticket/front/descriptor/addStowaway.html index 3efaedc8d..ee587dae0 100644 --- a/modules/ticket/front/descriptor/addStowaway.html +++ b/modules/ticket/front/descriptor/addStowaway.html @@ -6,7 +6,7 @@ + on-open="model.refresh()">
Stowaways to add
From 1186654fbacd5e8d31f4c2ed4869bb615ec0460e Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 8 Oct 2019 13:51:16 +0200 Subject: [PATCH 04/46] added invoiceOut alias --- modules/invoiceOut/back/methods/invoiceOut/filter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/filter.js b/modules/invoiceOut/back/methods/invoiceOut/filter.js index 001fe077d..092d298d0 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/filter.js +++ b/modules/invoiceOut/back/methods/invoiceOut/filter.js @@ -86,8 +86,9 @@ module.exports = Self => { return {'i.hasPdf': value}; case 'created': return {'i.created': value}; - case 'amount': case 'clientFk': + return {'i.clientFk': value}; + case 'amount': case 'companyFk': case 'issued': case 'dued': From cc71f51f45271e834d381304812ed68969d06df8 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 8 Oct 2019 13:51:16 +0200 Subject: [PATCH 05/46] added invoiceOut alias --- modules/invoiceOut/back/methods/invoiceOut/filter.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/modules/invoiceOut/back/methods/invoiceOut/filter.js b/modules/invoiceOut/back/methods/invoiceOut/filter.js index 001fe077d..092d298d0 100644 --- a/modules/invoiceOut/back/methods/invoiceOut/filter.js +++ b/modules/invoiceOut/back/methods/invoiceOut/filter.js @@ -86,8 +86,9 @@ module.exports = Self => { return {'i.hasPdf': value}; case 'created': return {'i.created': value}; - case 'amount': case 'clientFk': + return {'i.clientFk': value}; + case 'amount': case 'companyFk': case 'issued': case 'dued': From c0403873e78a8cc9e2b464b8d02b11e88d70641f Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 8 Oct 2019 14:36:02 +0200 Subject: [PATCH 06/46] stowaway changed to correct field name --- modules/ticket/back/methods/ticket/getPossibleStowaways.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/getPossibleStowaways.js b/modules/ticket/back/methods/ticket/getPossibleStowaways.js index f692c9f23..3565d64ab 100644 --- a/modules/ticket/back/methods/ticket/getPossibleStowaways.js +++ b/modules/ticket/back/methods/ticket/getPossibleStowaways.js @@ -45,7 +45,7 @@ module.exports = Self => { clientFk: ship.clientFk, addressFk: ship.addressFk, agencyModeFk: ship.agencyModeFk, - warehouse: {neq: ship.warehouseFk}, + warehouseFk: {neq: ship.warehouseFk}, shipped: { between: [lowestDate.toJSON(), highestDate.toJSON()] } From 6422d25ad616ebf7ff19924e203167210c1abef9 Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Tue, 8 Oct 2019 14:36:02 +0200 Subject: [PATCH 07/46] stowaway changed to correct field name --- modules/ticket/back/methods/ticket/getPossibleStowaways.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/modules/ticket/back/methods/ticket/getPossibleStowaways.js b/modules/ticket/back/methods/ticket/getPossibleStowaways.js index f692c9f23..3565d64ab 100644 --- a/modules/ticket/back/methods/ticket/getPossibleStowaways.js +++ b/modules/ticket/back/methods/ticket/getPossibleStowaways.js @@ -45,7 +45,7 @@ module.exports = Self => { clientFk: ship.clientFk, addressFk: ship.addressFk, agencyModeFk: ship.agencyModeFk, - warehouse: {neq: ship.warehouseFk}, + warehouseFk: {neq: ship.warehouseFk}, shipped: { between: [lowestDate.toJSON(), highestDate.toJSON()] } From 7db4945a6d53b062b46488e8c70dcf8218d343dd Mon Sep 17 00:00:00 2001 From: Carlos Jimenez Ruiz Date: Tue, 8 Oct 2019 17:27:27 +0200 Subject: [PATCH 08/46] #1702 Autocomplete data refresh and #1754 watcher --- e2e/helpers/selectors.js | 1 + e2e/paths/04-item-module/03_tax.spec.js | 27 ++++++-- .../components/autocomplete/autocomplete.js | 4 +- front/core/components/watcher/watcher.js | 7 +- modules/item/front/tax/index.html | 5 +- modules/item/front/tax/index.js | 21 +++--- modules/item/front/tax/index.spec.js | 66 +++++++++---------- 7 files changed, 72 insertions(+), 59 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 351053a02..a1aac1adf 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -260,6 +260,7 @@ export default { submitItemTagsButton: `vn-item-tags ${components.vnSubmit}` }, itemTax: { + undoChangesButton: 'vn-item-tax vn-button-bar > vn-button[label="Undo changes"]', firstClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(1) > vn-autocomplete[field="tax.taxClassFk"]', secondClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(2) > vn-autocomplete[field="tax.taxClassFk"]', thirdClassAutocomplete: 'vn-item-tax vn-horizontal:nth-child(3) > vn-autocomplete[field="tax.taxClassFk"]', diff --git a/e2e/paths/04-item-module/03_tax.spec.js b/e2e/paths/04-item-module/03_tax.spec.js index 38861f1bf..903d05f10 100644 --- a/e2e/paths/04-item-module/03_tax.spec.js +++ b/e2e/paths/04-item-module/03_tax.spec.js @@ -1,8 +1,7 @@ import selectors from '../../helpers/selectors.js'; import createNightmare from '../../helpers/nightmare'; -// #1702 Autocomplete no siempre refresca al cancelar formulario -xdescribe('Item edit tax path', () => { +describe('Item edit tax path', () => { const nightmare = createNightmare(); beforeAll(() => { @@ -14,9 +13,9 @@ xdescribe('Item edit tax path', () => { it(`should add the item tax to all countries`, async() => { const result = await nightmare - .autocompleteSearch(selectors.itemTax.firstClassAutocomplete, 'Reduced VAT') + .autocompleteSearch(selectors.itemTax.firstClassAutocomplete, 'General VAT') .autocompleteSearch(selectors.itemTax.secondClassAutocomplete, 'General VAT') - .autocompleteSearch(selectors.itemTax.thirdClassAutocomplete, 'Reduced VAT') + .autocompleteSearch(selectors.itemTax.thirdClassAutocomplete, 'General VAT') .waitToClick(selectors.itemTax.submitTaxButton) .waitForLastSnackbar(); @@ -28,7 +27,7 @@ xdescribe('Item edit tax path', () => { .reloadSection('item.card.tax') .waitToGetProperty(`${selectors.itemTax.firstClassAutocomplete} input`, 'value'); - expect(firstVatType).toEqual('Reduced VAT'); + expect(firstVatType).toEqual('General VAT'); }); it(`should confirm the second item tax class was edited`, async() => { @@ -42,6 +41,22 @@ xdescribe('Item edit tax path', () => { const thirdVatType = await nightmare .waitToGetProperty(`${selectors.itemTax.thirdClassAutocomplete} input`, 'value'); - expect(thirdVatType).toEqual('Reduced VAT'); + expect(thirdVatType).toEqual('General VAT'); + }); + + it(`should edit the first class without saving the form`, async() => { + const firstVatType = await nightmare + .autocompleteSearch(selectors.itemTax.firstClassAutocomplete, 'Reduced VAT') + .waitToGetProperty(`${selectors.itemTax.firstClassAutocomplete} input`, 'value'); + + expect(firstVatType).toEqual('Reduced VAT'); + }); + + it(`should now click the undo changes button and see the changes works`, async() => { + const firstVatType = await nightmare + .waitToClick(selectors.itemTax.undoChangesButton) + .waitToGetProperty(`${selectors.itemTax.firstClassAutocomplete} input`, 'value'); + + expect(firstVatType).toEqual('General VAT'); }); }); diff --git a/front/core/components/autocomplete/autocomplete.js b/front/core/components/autocomplete/autocomplete.js index 469bb9e93..ce081b58a 100755 --- a/front/core/components/autocomplete/autocomplete.js +++ b/front/core/components/autocomplete/autocomplete.js @@ -136,8 +136,8 @@ export default class Autocomplete extends Input { return; const selection = this.fetchSelection(); - if (!this.selection) - this.selection = selection; + + this.selection = selection; } fetchSelection() { diff --git a/front/core/components/watcher/watcher.js b/front/core/components/watcher/watcher.js index a085ee45f..02b92dda6 100644 --- a/front/core/components/watcher/watcher.js +++ b/front/core/components/watcher/watcher.js @@ -223,11 +223,8 @@ export default class Watcher extends Component { } loadOriginalData() { - Object.keys(this.data).forEach(key => { - delete this.data[key]; - }); - - this.data = Object.assign(this.data, this.orgData); + const orgData = JSON.parse(JSON.stringify(this.orgData)); + this.data = Object.assign(this.data, orgData); this.setPristine(); } diff --git a/modules/item/front/tax/index.html b/modules/item/front/tax/index.html index e0d58ba1a..62c4e305c 100644 --- a/modules/item/front/tax/index.html +++ b/modules/item/front/tax/index.html @@ -1,5 +1,5 @@ @@ -11,7 +11,7 @@
- + diff --git a/modules/item/front/tax/index.js b/modules/item/front/tax/index.js index f4cc6f73e..84a847e05 100644 --- a/modules/item/front/tax/index.js +++ b/modules/item/front/tax/index.js @@ -1,11 +1,11 @@ import ngModule from '../module'; export default class Controller { - constructor($stateParams, $http, $translate, vnApp) { + constructor($stateParams, $http, $translate, $scope) { + this.$ = $scope; this.$http = $http; this.$stateParams = $stateParams; this._ = $translate; - this.vnApp = vnApp; } $onInit() { @@ -21,9 +21,8 @@ export default class Controller { }] }; - let urlFilter = encodeURIComponent(JSON.stringify(filter)); - let url = `/item/api/Items/${this.$stateParams.id}/taxes?filter=${urlFilter}`; - this.$http.get(url).then(json => { + let url = `api/Items/${this.$stateParams.id}/taxes`; + this.$http.get(url, {params: {filter}}).then(json => { this.taxes = json.data; }); } @@ -33,14 +32,16 @@ export default class Controller { for (let tax of this.taxes) data.push({id: tax.id, taxClassFk: tax.taxClassFk}); - let url = `/item/api/Items/updateTaxes`; - this.$http.post(url, data).then( - () => this.vnApp.showSuccess(this._.instant('Data saved!')) - ); + this.$.watcher.check(); + let url = `api/Items/updateTaxes`; + this.$http.post(url, data).then(() => { + this.$.watcher.notifySaved(); + this.$.watcher.updateOriginalData(); + }); } } -Controller.$inject = ['$stateParams', '$http', '$translate', 'vnApp']; +Controller.$inject = ['$stateParams', '$http', '$translate', '$scope']; ngModule.component('vnItemTax', { template: require('./index.html'), diff --git a/modules/item/front/tax/index.spec.js b/modules/item/front/tax/index.spec.js index 56c3b9306..59d8ad892 100644 --- a/modules/item/front/tax/index.spec.js +++ b/modules/item/front/tax/index.spec.js @@ -2,65 +2,65 @@ import './index.js'; describe('Item', () => { describe('Component vnItemTax', () => { + let $element; let $stateParams; let controller; let $httpBackend; - let vnApp; beforeEach(angular.mock.module('item', $translateProvider => { $translateProvider.translations('en', {}); })); - beforeEach(angular.mock.inject(($componentController, _$httpBackend_, _$stateParams_, _vnApp_) => { + beforeEach(angular.mock.inject((_$httpBackend_, $rootScope, _$stateParams_, $compile) => { $stateParams = _$stateParams_; $stateParams.id = 1; $httpBackend = _$httpBackend_; - vnApp = _vnApp_; - spyOn(vnApp, 'showSuccess'); - controller = $componentController('vnItemTax', {$state: $stateParams}); + + $httpBackend.whenGET(url => url.startsWith(`api/TaxClasses`)) + .respond([ + {id: 1, description: 'Reduced VAT', code: 'R'}, + {id: 2, description: 'General VAT', code: 'G'} + ]); + + $httpBackend.whenGET(url => url.startsWith(`api/Items/${$stateParams.id}/taxes`)) + .respond([ + {id: 1, taxClassFk: 1} + ]); + + $element = $compile(` { + $element.remove(); + }); + describe('getTaxes()', () => { it('should perform a query to set the array of taxes into the controller', () => { - let filter = { - fields: ['id', 'countryFk', 'taxClassFk'], - include: [{ - relation: 'country', - scope: {fields: ['country']} - }] - }; - let response = [{id: 1, taxClassFk: 1}]; - filter = encodeURIComponent(JSON.stringify(filter)); - $httpBackend.when('GET', `/item/api/Items/1/taxes?filter=${filter}`).respond(response); - $httpBackend.expect('GET', `/item/api/Items/1/taxes?filter=${filter}`); - controller.$onInit(); $httpBackend.flush(); - expect(controller.taxes).toEqual(response); + expect(controller.taxes[0].id).toEqual(1); + expect(controller.taxes[0].taxClassFk).toEqual(1); }); }); describe('submit()', () => { it('should perform a post to update taxes', () => { - let filter = { - fields: ['id', 'countryFk', 'taxClassFk'], - include: [{ - relation: 'country', - scope: {fields: ['country']} - }] - }; - let response = [{id: 1, taxClassFk: 1}]; - filter = encodeURIComponent(JSON.stringify(filter)); - $httpBackend.when('GET', `/item/api/Items/1/taxes?filter=${filter}`).respond(response); - controller.$onInit(); - $httpBackend.flush(); + spyOn(controller.$.watcher, 'notifySaved'); + spyOn(controller.$.watcher, 'updateOriginalData'); + controller.taxes = [ + {id: 37, countryFk: 1, taxClassFk: 1, country: {id: 1, country: 'España'}} + ]; + controller.$.watcher.data = [ + {id: 37, countryFk: 1, taxClassFk: 2, country: {id: 1, country: 'España'}} + ]; - $httpBackend.when('POST', `/item/api/Items/updateTaxes`).respond('ok'); - $httpBackend.expect('POST', `/item/api/Items/updateTaxes`); + $httpBackend.whenPOST(`api/Items/updateTaxes`).respond('oki doki'); controller.submit(); $httpBackend.flush(); - expect(vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); + expect(controller.$.watcher.notifySaved).toHaveBeenCalledWith(); + expect(controller.$.watcher.updateOriginalData).toHaveBeenCalledWith(); }); }); }); From 757fc6fe23d1198de3c09307ab46f5af64ce3571 Mon Sep 17 00:00:00 2001 From: Juan Ferrer Toribio Date: Tue, 8 Oct 2019 23:57:02 +0200 Subject: [PATCH 09/46] vnField stable & applied to all field except vnTextfield --- e2e/helpers/components_selectors.js | 4 +- e2e/helpers/extensions.js | 44 +++---- e2e/helpers/selectors.js | 60 +++++----- .../components/autocomplete/autocomplete.html | 27 ----- front/core/components/autocomplete/index.html | 46 ++++++++ .../{autocomplete.js => index.js} | 95 +++++----------- .../{autocomplete.spec.js => index.spec.js} | 0 front/core/components/autocomplete/style.scss | 61 +--------- front/core/components/check/index.js | 6 +- front/core/components/check/index.spec.js | 2 +- .../components/date-picker/date-picker.html | 21 ---- .../components/date-picker/date-picker.js | 107 ------------------ .../date-picker/date-picker.spec.js | 37 ------ front/core/components/date-picker/index.js | 101 +++++++++++++++++ .../core/components/date-picker/index.spec.js | 45 ++++++++ front/core/components/date-picker/style.scss | 19 ---- front/core/components/drop-down/drop-down.js | 2 + front/core/components/field/index.html | 6 +- front/core/components/field/index.js | 98 ++++++++++++---- front/core/components/field/style.scss | 9 +- front/core/components/index.js | 6 +- front/core/components/input-number/index.html | 90 +++++++-------- front/core/components/input-number/index.js | 94 ++++----------- .../components/input-number/index.spec.js | 83 +++++++------- front/core/components/input-number/style.scss | 16 --- front/core/components/input-time/index.html | 26 ----- front/core/components/input-time/index.js | 74 +++--------- .../core/components/input-time/index.spec.js | 43 +++---- front/core/components/input-time/style.scss | 12 -- front/core/components/popover/popover.js | 5 +- front/core/components/radio/index.js | 6 +- front/core/components/toggle/index.js | 2 +- front/core/module.js | 37 ++++++ loopback/locale/en.json | 3 +- loopback/locale/es.json | 3 +- modules/agency/front/basic-data/index.html | 37 +++--- modules/agency/front/create/index.html | 49 +++++--- modules/agency/front/edit/index.html | 40 ++++--- modules/agency/front/events/index.html | 14 +-- modules/claim/front/basic-data/index.html | 4 +- modules/claim/front/detail/index.html | 14 +-- modules/claim/front/search-panel/index.html | 2 +- .../client/front/balance/create/index.html | 14 ++- modules/client/front/billing-data/index.html | 29 +++-- .../front/credit-insurance/create/index.html | 16 ++- .../insurance/create/index.html | 19 ++-- .../insurance/index/index.html | 60 +++++----- modules/client/front/credit/create/index.html | 7 +- modules/client/front/greuge/create/index.html | 25 ++-- .../client/front/recovery/create/index.html | 28 +++-- .../invoiceOut/front/search-panel/index.html | 6 +- modules/item/front/basic-data/index.html | 28 +++-- modules/item/front/last-entries/index.html | 3 +- .../front/request-search-panel/index.html | 4 +- modules/item/front/request/index.html | 8 +- modules/order/front/basic-data/index.html | 3 +- modules/order/front/create/card.html | 3 +- modules/order/front/prices-popover/index.html | 5 +- modules/order/front/search-panel/index.html | 10 +- modules/route/front/basic-data/index.html | 16 +-- modules/route/front/create/index.html | 3 +- modules/route/front/search-panel/index.html | 10 +- .../front/basic-data/step-one/index.html | 12 +- modules/ticket/front/create/card.html | 3 +- modules/ticket/front/descriptor/index.html | 7 +- modules/ticket/front/package/index.html | 6 +- .../ticket/front/request/create/index.html | 14 ++- modules/ticket/front/sale/editDiscount.html | 8 +- modules/ticket/front/sale/index.html | 26 +++-- modules/ticket/front/search-panel/index.html | 9 +- modules/ticket/front/services/index.html | 12 +- modules/travel/front/search-panel/index.html | 4 +- modules/worker/front/time-control/index.html | 7 +- 73 files changed, 905 insertions(+), 950 deletions(-) delete mode 100755 front/core/components/autocomplete/autocomplete.html create mode 100755 front/core/components/autocomplete/index.html rename front/core/components/autocomplete/{autocomplete.js => index.js} (80%) rename front/core/components/autocomplete/{autocomplete.spec.js => index.spec.js} (100%) delete mode 100644 front/core/components/date-picker/date-picker.html delete mode 100644 front/core/components/date-picker/date-picker.js delete mode 100644 front/core/components/date-picker/date-picker.spec.js create mode 100644 front/core/components/date-picker/index.js create mode 100644 front/core/components/date-picker/index.spec.js delete mode 100644 front/core/components/input-number/style.scss delete mode 100644 front/core/components/input-time/index.html delete mode 100644 front/core/components/input-time/style.scss diff --git a/e2e/helpers/components_selectors.js b/e2e/helpers/components_selectors.js index 4cd8241ab..3e2715ba2 100644 --- a/e2e/helpers/components_selectors.js +++ b/e2e/helpers/components_selectors.js @@ -1,6 +1,6 @@ export default { - vnTextfield: 'vn-textfield > div > div > div > input', - vnInputNumber: 'vn-input-number > div > div > div > input', + vnTextfield: 'vn-textfield input', + vnInputNumber: 'vn-input-number input', vnSubmit: 'vn-submit > input', vnFloatButton: 'vn-float-button > button' }; diff --git a/e2e/helpers/extensions.js b/e2e/helpers/extensions.js index 081332337..c000a471a 100644 --- a/e2e/helpers/extensions.js +++ b/e2e/helpers/extensions.js @@ -18,8 +18,18 @@ let actions = { clearInput: function(selector, done) { this.wait(selector) - .evaluate(inputSelector => { - return document.querySelector(inputSelector).closest('*[model], *[field], *[value]').$ctrl.value = ''; + .evaluate(selector => { + let field = document.querySelector(selector) + .closest('*[model], *[field], *[value]'); + let $ctrl = field.$ctrl; + + if (field.classList.contains('vn-field')) { + $ctrl.field = null; + $ctrl.$.$apply(); + } else + $ctrl.value = null; + + $ctrl.input.dispatchEvent(new Event('change')); }, selector) .then(done) .catch(done); @@ -167,8 +177,8 @@ let actions = { focusElement: function(selector, done) { this.wait(selector) - .evaluate_now(elemenetSelector => { - let element = document.querySelector(elemenetSelector); + .evaluate_now(selector => { + let element = document.querySelector(selector); element.focus(); }, done, selector) .then(done) @@ -401,8 +411,7 @@ let actions = { }, autocompleteSearch: function(autocompleteSelector, searchValue, done) { - this.wait(`${autocompleteSelector} input`) - .waitToClick(`${autocompleteSelector} input`) + this.waitToClick(`${autocompleteSelector} input`) .write(`.vn-popover.shown .vn-drop-down input`, searchValue) .waitToClick(`.vn-popover.shown .vn-drop-down li.active`) .wait((autocompleteSelector, searchValue) => { @@ -412,7 +421,7 @@ let actions = { }, autocompleteSelector, searchValue) .then(done) .catch(() => { - done(new Error(`.autocompleteSearch() for ${autocompleteSelector}, timed out`)); + done(new Error(`.autocompleteSearch() for value ${searchValue} in ${autocompleteSelector} timed out`)); }); }, @@ -427,25 +436,22 @@ let actions = { .catch(done); }, - datePicker: function(datePickerSelector, changeMonth, day, done) { - this.wait(datePickerSelector) - .mousedown(datePickerSelector) - .wait('div.flatpickr-calendar.open'); + datePicker: function(selector, changeMonth, day, done) { + this.wait(selector) + .mousedown(`${selector} input`) + .wait('.flatpickr-calendar.open'); + if (changeMonth > 0) - this.mousedown('body > div.flatpickr-calendar.open > div.flatpickr-months > span.flatpickr-next-month > svg'); - - + this.mousedown(`.flatpickr-calendar.open .flatpickr-next-month`); if (changeMonth < 0) - this.mousedown('body > div.flatpickr-calendar.open > div.flatpickr-months > span.flatpickr-prev-month > svg'); + this.mousedown(`.flatpickr-calendar.open .flatpickr-prev-month`); let daySelector; if (!day) - daySelector = 'div.flatpickr-calendar.open span.flatpickr-day:nth-child(16)'; - + daySelector = `.flatpickr-calendar.open .flatpickr-day:nth-child(16)`; if (day) - daySelector = `span.flatpickr-day[aria-label~="${day},"]:not(.prevMonthDay):not(.nextMonthDay)`; - + daySelector = `.flatpickr-calendar.open .flatpickr-day[aria-label~="${day},"]:not(.prevMonthDay):not(.nextMonthDay)`; this.wait(selector => { return document.querySelector(selector); diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 351053a02..b032caf0d 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -16,9 +16,9 @@ export default { userLocalCompany: '.user-configuration vn-autocomplete[field="$ctrl.localCompanyFk"]', userWarehouse: '.user-configuration vn-autocomplete[field="$ctrl.warehouseFk"]', userCompany: '.user-configuration vn-autocomplete[field="$ctrl.companyFk"]', - userConfigFirstAutocompleteClear: '#localWarehouse > div > div > div > vn-icon.clear', - userConfigSecondAutocompleteClear: '#localBank > div > div > div > vn-icon.clear', - userConfigThirdAutocompleteClear: '#localCompany > div > div > div > vn-icon.clear', + userConfigFirstAutocompleteClear: '#localWarehouse .icons > vn-icon[icon=clear]', + userConfigSecondAutocompleteClear: '#localBank .icons > vn-icon[icon=clear]', + userConfigThirdAutocompleteClear: '#localCompany .icons > vn-icon[icon=clear]', acceptButton: 'vn-confirm button[response=ACCEPT]' }, clientsIndex: { @@ -79,14 +79,14 @@ export default { saveButton: `${components.vnSubmit}` }, clientBillingData: { - payMethodAutocomplete: 'vn-autocomplete[field="$ctrl.client.payMethodFk"]', - IBANInput: `${components.vnTextfield}[name="iban"]`, - dueDayInput: `${components.vnInputNumber}[name="dueDay"]`, - receivedCoreLCRCheckbox: 'vn-check[label="Received LCR"]', - receivedCoreVNLCheckbox: 'vn-check[label="Received core VNL"]', - receivedB2BVNLCheckbox: 'vn-check[label="Received B2B VNL"]', + payMethodAutocomplete: 'vn-client-billing-data vn-autocomplete[field="$ctrl.client.payMethodFk"]', + IBANInput: `vn-client-billing-data ${components.vnTextfield}[name="iban"]`, + dueDayInput: `vn-client-billing-data ${components.vnInputNumber}[name="dueDay"]`, + receivedCoreLCRCheckbox: 'vn-client-billing-data vn-check[label="Received LCR"]', + receivedCoreVNLCheckbox: 'vn-client-billing-data vn-check[label="Received core VNL"]', + receivedB2BVNLCheckbox: 'vn-client-billing-data vn-check[label="Received B2B VNL"]', swiftBicAutocomplete: 'vn-client-billing-data vn-autocomplete[field="$ctrl.client.bankEntityFk"]', - clearswiftBicButton: 'vn-client-billing-data vn-autocomplete[field="$ctrl.client.bankEntityFk"] > div > div > div > vn-icon > i', + clearswiftBicButton: 'vn-client-billing-data vn-autocomplete[field="$ctrl.client.bankEntityFk"] .icons > vn-icon[icon=clear]', newBankEntityButton: 'vn-client-billing-data vn-icon-button[vn-tooltip="New bank entity"] > button', newBankEntityName: 'vn-client-billing-data > vn-dialog vn-textfield[label="Name"] input', newBankEntityBIC: 'vn-client-billing-data > vn-dialog vn-textfield[label="Swift / BIC"] input', @@ -345,7 +345,7 @@ export default { createTicketView: { clientAutocomplete: 'vn-ticket-create vn-autocomplete[field="$ctrl.clientFk"]', addressAutocomplete: 'vn-ticket-create vn-autocomplete[field="$ctrl.addressFk"]', - deliveryDateInput: 'vn-ticket-create > div > div > vn-card > div > vn-ticket-create-card > vn-date-picker > div > input', + deliveryDateInput: 'vn-ticket-create vn-date-picker[field="$ctrl.landed"]', warehouseAutocomplete: 'vn-ticket-create vn-autocomplete[field="$ctrl.warehouseFk"]', agencyAutocomplete: 'vn-ticket-create vn-autocomplete[field="$ctrl.ticket.agencyModeFk"]', createButton: `${components.vnSubmit}` @@ -392,7 +392,7 @@ export default { firstQuantityInput: 'vn-input-number[label="Quantity"] input', firstRemovePackageButton: 'vn-icon-button[vn-tooltip="Remove package"]', addPackageButton: 'vn-icon-button[vn-tooltip="Add package"]', - clearPackageAutocompleteButton: 'vn-autocomplete[label="Package"] > div > div > div > vn-icon > i', + clearPackageAutocompleteButton: 'vn-autocomplete[label="Package"] .icons > vn-icon[icon=clear]', savePackagesButton: `${components.vnSubmit}` }, ticketSales: { @@ -408,7 +408,7 @@ export default { moreMenuReserve: '.vn-popover.shown .vn-drop-down li[name="Mark as reserved"]', moreMenuUnmarkReseved: '.vn-popover.shown .vn-drop-down li[name="Unmark as reserved"]', moreMenuUpdateDiscount: '.vn-popover.shown .vn-drop-down li[name="Update discount"]', - moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog form vn-ticket-sale-edit-discount vn-input-number[model="$ctrl.newDiscount"] input', + moreMenuUpdateDiscountInput: 'vn-ticket-sale vn-dialog form vn-ticket-sale-edit-discount vn-input-number[field="$ctrl.newDiscount"] input', transferQuantityInput: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable > span > text', transferQuantityCell: '.vn-popover.shown vn-table > div > vn-tbody > vn-tr > vn-td-editable', firstSaleClaimIcon: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) vn-icon[icon="icon-claims"]', @@ -416,11 +416,11 @@ export default { firstSaleText: 'vn-table div > vn-tbody > vn-tr:nth-child(1)', firstSaleThumbnailImage: 'vn-ticket-sale:nth-child(1) vn-tr:nth-child(1) vn-td:nth-child(3) > img', firstSaleZoomedImage: 'body > div > div > img', - firstSaleQuantity: 'vn-input-number[model="sale.quantity"]:nth-child(1) input', + firstSaleQuantity: 'vn-input-number[field="sale.quantity"]:nth-child(1) input', firstSaleQuantityCell: 'vn-ticket-sale vn-tr:nth-child(1) > vn-td-editable:nth-child(5)', firstSaleQuantityClearInput: 'vn-textfield[model="sale.quantity"] div.suffix > i', - firstSaleIdInput: 'body > vn-app > div > ui-view > vn-ticket-card > vn-main-block > div > vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete > div > div > input', - firstSaleIdAutocomplete: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete', + firstSaleIdInput: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete input', + firstSaleIdAutocomplete: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(4) > vn-autocomplete', idAutocompleteFirstResult: '.vn-popover.shown .vn-drop-down li', firstSalePrice: 'vn-ticket-sale vn-table vn-tr:nth-child(1) > vn-td:nth-child(7) > span', firstSalePriceInput: '.vn-popover.shown vn-input-number input', @@ -438,10 +438,10 @@ export default { secondSaleText: 'vn-table div > vn-tbody > vn-tr:nth-child(2)', secondSaleId: 'vn-ticket-sale:nth-child(2) vn-td-editable:nth-child(4) text > span', secondSaleIdCell: 'vn-ticket-sale vn-tr:nth-child(2) > vn-td-editable:nth-child(4)', - secondSaleIdInput: 'body > vn-app > div > ui-view > vn-ticket-card > vn-main-block > div > vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-autocomplete > div > div > input', - secondSaleIdAutocomplete: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-autocomplete', + secondSaleIdInput: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-autocomplete input', + secondSaleIdAutocomplete: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(4) > vn-autocomplete', secondSaleQuantity: 'vn-ticket-sale vn-table vn-tr:nth-child(2) vn-input-number input', - secondSaleConceptCell: 'vn-ticket-sale vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td-editable:nth-child(6)', + secondSaleConceptCell: 'vn-ticket-sale vn-table vn-tbody > vn-tr:nth-child(2) > vn-td-editable:nth-child(6)', secondSaleConceptInput: 'vn-ticket-sale vn-table vn-tr:nth-child(2) > vn-td-editable.ng-isolate-scope.selected vn-textfield input', totalImport: 'vn-ticket-sale > vn-vertical > vn-card > div > vn-vertical > vn-horizontal > vn-one > p:nth-child(3) > strong', selectAllSalesCheckbox: 'vn-ticket-sale vn-thead vn-check', @@ -485,8 +485,8 @@ export default { request: 'vn-ticket-request-index > form > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr', descriptionInput: 'vn-ticket-request-create > form > div > vn-card > div > vn-horizontal:nth-child(1) > vn-textfield > div > div > div.infix > input', atenderAutocomplete: 'vn-ticket-request-create vn-autocomplete[field="$ctrl.ticketRequest.atenderFk"]', - quantityInput: 'vn-ticket-request-create > form > div > vn-card > div > vn-horizontal:nth-child(2) > vn-input-number:nth-child(1) > div > div > div.infix > input', - priceInput: 'vn-ticket-request-create > form > div > vn-card > div > vn-horizontal:nth-child(2) > vn-input-number:nth-child(2) > div > div > div.infix > input', + quantityInput: 'vn-ticket-request-create vn-input-number input[name=quantity]', + priceInput: 'vn-ticket-request-create vn-input-number input[name=price]', firstRemoveRequestButton: 'vn-ticket-request-index vn-icon[icon="delete"]:nth-child(1)', saveButton: 'vn-ticket-request-create > form > div > vn-button-bar > vn-submit[label="Create"] input', firstDescription: 'vn-ticket-request-index > form > vn-card > div > vn-horizontal > vn-table > div > vn-tbody > vn-tr:nth-child(1) > vn-td:nth-child(2)', @@ -514,7 +514,7 @@ export default { createStateView: { stateAutocomplete: 'vn-autocomplete[field="$ctrl.stateFk"]', workerAutocomplete: 'vn-autocomplete[field="$ctrl.workerFk"]', - clearStateInputButton: 'vn-autocomplete[field="$ctrl.stateFk"] > div > div > div > vn-icon > i', + clearStateInputButton: 'vn-autocomplete[field="$ctrl.stateFk"] .icons > vn-icon[icon=clear]', saveStateButton: `${components.vnSubmit}` }, claimsIndex: { @@ -548,12 +548,12 @@ export default { }, claimDetail: { secondItemDiscount: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(6) > span', - discountInput: '.vn-popover.shown vn-input-number[model="$ctrl.newDiscount"] > div > div > div.infix > input', + discountInput: '.vn-popover.shown vn-input-number[field="$ctrl.newDiscount"] > div > div > div.infix > input', discoutPopoverMana: '.vn-popover.shown .content > div > vn-horizontal > h5', addItemButton: 'vn-claim-detail a vn-float-button', firstClaimableSaleFromTicket: 'vn-claim-detail > vn-dialog vn-tbody > vn-tr', claimDetailLine: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr', - firstItemQuantityInput: 'vn-claim-detail vn-tr:nth-child(1) vn-input-number[model="saleClaimed.quantity"] input', + firstItemQuantityInput: 'vn-claim-detail vn-tr:nth-child(1) vn-input-number[field="saleClaimed.quantity"] input', totalClaimed: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-horizontal > div > vn-label-value:nth-child(2) > section > span', secondItemDeleteButton: 'vn-claim-detail > vn-vertical > vn-card > div > vn-vertical > vn-table > div > vn-tbody > vn-tr:nth-child(2) > vn-td:nth-child(8) > vn-icon-button > button > vn-icon > i' }, @@ -597,7 +597,7 @@ export default { clientAutocomplete: 'vn-autocomplete[label="Client"]', addressAutocomplete: 'vn-autocomplete[label="Address"]', agencyAutocomplete: 'vn-autocomplete[label="Agency"]', - landedDatePicker: 'vn-date-picker[label="Landed"] input', + landedDatePicker: 'vn-date-picker[label="Landed"]', createButton: `${components.vnSubmit}`, cancelButton: 'vn-button[href="#!/client/index"]' }, @@ -633,7 +633,7 @@ export default { }, createRouteView: { workerAutocomplete: 'vn-route-create vn-autocomplete[field="$ctrl.route.workerFk"]', - createdDatePicker: 'vn-route-create vn-date-picker[model="$ctrl.route.created"] > div > input', + createdDatePicker: 'vn-route-create vn-date-picker[field="$ctrl.route.created"]', vehicleAutoComplete: 'vn-route-create vn-autocomplete[field="$ctrl.route.vehicleFk"]', agencyAutoComplete: 'vn-route-create vn-autocomplete[field="$ctrl.route.agencyModeFk"]', descriptionInput: 'vn-route-create vn-textfield[field="$ctrl.route.description"] input', @@ -650,10 +650,10 @@ export default { vehicleAutoComplete: 'vn-route-basic-data vn-autocomplete[field="$ctrl.route.vehicleFk"]', agencyAutoComplete: 'vn-route-basic-data vn-autocomplete[field="$ctrl.route.agencyModeFk"]', kmStartInput: 'vn-route-basic-data vn-input-number[field="$ctrl.route.kmStart"] input', - kmEndInput: 'vn-route-basic-data vn-input-number[model="$ctrl.route.kmEnd"] input', - createdDateInput: 'vn-route-basic-data vn-date-picker[model="$ctrl.route.created"] > div > input', - startedHourInput: 'vn-route-basic-data vn-input-time[model="$ctrl.route.started"] input', - finishedHourInput: 'vn-route-basic-data vn-input-time[model="$ctrl.route.finished"] input', + kmEndInput: 'vn-route-basic-data vn-input-number[field="$ctrl.route.kmEnd"] input', + createdDateInput: 'vn-route-basic-data vn-date-picker[field="$ctrl.route.created"]', + startedHourInput: 'vn-route-basic-data vn-input-time[field="$ctrl.route.started"] input', + finishedHourInput: 'vn-route-basic-data vn-input-time[field="$ctrl.route.finished"] input', saveButton: 'vn-route-basic-data vn-submit[label="Save"] input' }, routeTickets: { diff --git a/front/core/components/autocomplete/autocomplete.html b/front/core/components/autocomplete/autocomplete.html deleted file mode 100755 index 4caca44bc..000000000 --- a/front/core/components/autocomplete/autocomplete.html +++ /dev/null @@ -1,27 +0,0 @@ -
-
- -
- - -
- -
-
- - \ No newline at end of file diff --git a/front/core/components/autocomplete/index.html b/front/core/components/autocomplete/index.html new file mode 100755 index 000000000..90f936801 --- /dev/null +++ b/front/core/components/autocomplete/index.html @@ -0,0 +1,46 @@ +
+
+
+
+
+
+ + +
+
+ +
+
+ + + + +
+
+
+
+
+
+
+ + \ No newline at end of file diff --git a/front/core/components/autocomplete/autocomplete.js b/front/core/components/autocomplete/index.js similarity index 80% rename from front/core/components/autocomplete/autocomplete.js rename to front/core/components/autocomplete/index.js index 469bb9e93..f799ee3a9 100755 --- a/front/core/components/autocomplete/autocomplete.js +++ b/front/core/components/autocomplete/index.js @@ -1,5 +1,5 @@ import ngModule from '../../module'; -import Input from '../../lib/input'; +import Field from '../field'; import assignProps from '../../lib/assign-props'; import {mergeWhere} from 'vn-loopback/util/filter'; import './style.scss'; @@ -16,23 +16,18 @@ import './style.scss'; * * @event change Thrown when value is changed */ -export default class Autocomplete extends Input { - constructor($element, $scope, $http, $transclude, $translate, $interpolate) { - super($element, $scope); - this.$http = $http; - this.$interpolate = $interpolate; - this.$transclude = $transclude; - this.$translate = $translate; - this._field = undefined; +export default class Autocomplete extends Field { + constructor($element, $scope, $compile, $http, $transclude, $translate, $interpolate) { + super($element, $scope, $compile); + Object.assign(this, { + $http, + $interpolate, + $transclude, + $translate + }); + this._selection = null; - this.readonly = true; - this.form = null; - this.input = this.element.querySelector('.mdl-textfield__input'); - - componentHandler.upgradeElement( - this.element.querySelector('.mdl-textfield')); - - this.registerEvents(); + this.input = this.element.querySelector('input'); } $postLink() { @@ -44,12 +39,16 @@ export default class Autocomplete extends Input { } /** - * Registers all event emitters + * @type {any} The autocomplete value. */ - registerEvents() { - this.input.addEventListener('focus', event => { - this.emit('focus', {event}); - }); + get field() { + return super.field; + } + + set field(value) { + super.field = value; + this.refreshSelection(); + this.emit('change', {value}); } get model() { @@ -83,20 +82,6 @@ export default class Autocomplete extends Input { Object.assign(this.$.dropDown, props); } - /** - * @type {any} The autocomplete value. - */ - get field() { - return this._field; - } - - set field(value) { - this._field = value; - - this.refreshSelection(); - this.emit('change', {value}); - } - /** * @type {Object} The selected data object, you can use this property * to prevent requests to display the initial value. @@ -216,33 +201,15 @@ export default class Autocomplete extends Input { if (this.translateFields.indexOf(this.showField) > -1) this.input.value = this.$translate.instant(display); } - - this.mdlUpdate(); - } - - mdlUpdate() { - let field = this.element.querySelector('.mdl-textfield'); - let mdlField = field.MaterialTextfield; - if (mdlField) mdlField.updateClasses_(); - } - - setValue(value) { - this.field = value; - if (this.form) this.form.$setDirty(); } onDropDownSelect(item) { const value = item[this.valueField]; this.selection = item; - this.setValue(value); + this.field = value; } - onClearClick(event) { - event.preventDefault(); - this.setValue(null); - } - - onKeyDown(event) { + onInputKeyDown(event) { // if (event.defaultPrevented) return; switch (event.keyCode) { @@ -261,7 +228,8 @@ export default class Autocomplete extends Input { event.preventDefault(); } - onMouseDown(event) { + onInputMouseDown(event) { + if (event.defaultPrevented) return; event.preventDefault(); this.showDropDown(); } @@ -307,16 +275,12 @@ export default class Autocomplete extends Input { this.refreshSelection(); } } -Autocomplete.$inject = ['$element', '$scope', '$http', '$transclude', '$translate', '$interpolate']; +Autocomplete.$inject = ['$element', '$scope', '$compile', '$http', '$transclude', '$translate', '$interpolate']; -ngModule.component('vnAutocomplete', { - template: require('./autocomplete.html'), +ngModule.vnComponent('vnAutocomplete', { + template: require('./index.html'), controller: Autocomplete, bindings: { - label: '@', - field: '=?', - disabled: ' div > .mdl-textfield { - position: relative; - width: 100%; +vn-autocomplete.vn-field { + & > .container > .infix > .control { + overflow: hidden; & > input { cursor: pointer; - height: 30px; text-overflow: ellipsis; white-space: nowrap; overflow: hidden; + text-align: left; + padding-left: 0; + padding-right: 0; } - & > .icons { - display: none; - position: absolute; - right: 0; - top: 1.3em; - height: 1em; - color: $color-font-secondary; - border-radius: .2em; - - & > vn-icon { - cursor: pointer; - font-size: 18px; - - &:hover { - color: $color-font; - } - } - } - &:hover > .icons, - & > input:focus + .icons { - display: block; - } - } - - label span:nth-child(2) { - color: $color-alert } } - -ul.vn-autocomplete { - list-style-type: none; - padding: 1em; - margin: 0; - padding: 0; - overflow: auto; - max-height: 300px; - - li { - @extend %clickable; - display: block; - padding: .8em; - margin: 0; - - &.load-more { - color: $color-main; - font-family: vn-font-bold; - padding: .4em .8em; - } - } -} \ No newline at end of file diff --git a/front/core/components/check/index.js b/front/core/components/check/index.js index 35ff07e8a..8ebb784f3 100644 --- a/front/core/components/check/index.js +++ b/front/core/components/check/index.js @@ -64,14 +64,10 @@ export default class Check extends Toggle { } } -ngModule.component('vnCheck', { +ngModule.vnComponent('vnCheck', { template: require('./index.html'), controller: Check, bindings: { - label: '@?', - field: '=?', - disabled: ' { })); beforeEach(inject(($compile, $rootScope) => { - $element = $compile(``)($rootScope); $ctrl = $element.controller('vnCheck'); element = $element[0]; })); diff --git a/front/core/components/date-picker/date-picker.html b/front/core/components/date-picker/date-picker.html deleted file mode 100644 index 67fcd880b..000000000 --- a/front/core/components/date-picker/date-picker.html +++ /dev/null @@ -1,21 +0,0 @@ -
- -
- - clear - -
- -
\ No newline at end of file diff --git a/front/core/components/date-picker/date-picker.js b/front/core/components/date-picker/date-picker.js deleted file mode 100644 index 1156ab09a..000000000 --- a/front/core/components/date-picker/date-picker.js +++ /dev/null @@ -1,107 +0,0 @@ -import ngModule from '../../module'; -import Component from '../../lib/component'; -import {Flatpickr} from '../../vendor'; -import './style.scss'; - -class DatePicker extends Component { - constructor($element, $scope, $translate, $attrs) { - super($element, $scope); - this.input = $element[0].querySelector('input'); - this.$translate = $translate; - this.$attrs = $attrs; - this._model = undefined; - this.dateValue = undefined; - this.hasMouseIn = false; - let locale = this.$translate.use(); - this.defaultOptions = { - locale: locale, - dateFormat: locale == 'es' ? 'd-m-Y' : 'Y-m-d', - enableTime: false, - disableMobile: true, - onValueUpdate: () => this.onValueUpdate() - }; - this.userOptions = {}; - this._iniOptions = this.defaultOptions; - componentHandler.upgradeElement($element[0].firstChild); - this.vp = new Flatpickr(this.input, this._iniOptions); - } - - onValueUpdate() { - if (this.vp.selectedDates.length) { - let date = this.vp.selectedDates[0]; - let offset = date.getTimezoneOffset() * 60000; - date.setTime(date.getTime() - offset); - this._model = date; - } else - this.model = null; - this.$.$apply(); - } - - set iniOptions(value) { - this.userOptions = value; - let options = Object.assign({}, this.defaultOptions, value); - this._iniOptions = options; - - // TODO: When some properties change Flatpickr doesn't refresh the view - // for (let option in options) - // this.vp.set(option, options[option]); - - if (this.vp) this.vp.destroy(); - this.vp = new Flatpickr(this.input, this._iniOptions); - this.vp.setDate(this.dateValue); - this.mdlUpdate(); - } - - get iniOptions() { - return this.userOptions; - } - - get model() { - return this._model; - } - - set model(value) { - this._model = value; - this.dateValue = value; - let date; - if (value && this.iniOptions.enableTime) { - date = new Date(value); - let offset = date.getTimezoneOffset() * 60000; - date.setTime(date.getTime() + offset); - } else - date = value; - - this.vp.setDate(date); - this.mdlUpdate(); - } - - onClear() { - this.model = null; - } - - mdlUpdate() { - let mdlField = this.element.firstChild.MaterialTextfield; - if (mdlField) - mdlField.updateClasses_(); - } - - $onDestroy() { - this.vp.destroy(); - this.dateValue = undefined; - } -} -DatePicker.$inject = ['$element', '$scope', '$translate', '$attrs']; - -ngModule.component('vnDatePicker', { - template: require('./date-picker.html'), - bindings: { - iniOptions: ' { - let controller; - let $attrs; - let $element; - let today = new Date(); - today.setHours(0, 0, 0, 0); - - beforeEach(angular.mock.module('vnCore', $translateProvider => { - $translateProvider.translations('en', {}); - })); - - beforeEach(angular.mock.inject(($componentController, $translate) => { - $attrs = {}; - $element = angular.element(`
`); - controller = $componentController('vnDatePicker', {$element, $attrs, $translate}); - })); - - describe('onValueUpdate() while date is selected', () => { - it(`should store the selected date in the controller`, () => { - controller.vp = {selectedDates: [today]}; - controller.isLocale = true; - controller.onValueUpdate(); - - expect(controller._model).toEqual(today); - }); - - it(`should format the date`, () => { - controller.vp = {selectedDates: [today], destroy: () => {}}; - controller.isLocale = undefined; - controller._iniOptions.enableTime = undefined; - - controller.onValueUpdate(); - - expect(controller._model).toEqual(today); - }); - }); -}); diff --git a/front/core/components/date-picker/index.js b/front/core/components/date-picker/index.js new file mode 100644 index 000000000..96417f980 --- /dev/null +++ b/front/core/components/date-picker/index.js @@ -0,0 +1,101 @@ +import ngModule from '../../module'; +import Field from '../field'; +import {Flatpickr} from '../../vendor'; +import './style.scss'; + +class DatePicker extends Field { + constructor($element, $scope, $compile, $translate) { + super($element, $scope, $compile); + this.$translate = $translate; + + this.input = $compile(``)($scope)[0]; + this.control.appendChild(this.input); + + this.initPicker(); + } + + get field() { + return super.field; + } + + set field(value) { + super.field = value; + + let date = value; + if (date && !(date instanceof Date)) + date = new Date(date); + + this.picker.setDate(fixDate(date)); + } + + set options(value) { + let selectedDates = this.picker.selectedDates || []; + this._options = value; + this.initPicker(); + this.picker.setDate(selectedDates[0]); + } + + get options() { + return this._options; + } + + initPicker() { + let locale = this.$translate.use(); + let format = locale == 'es' ? 'd-m-Y' : 'Y-m-d'; + + let options = this.options || {}; + let defaultOptions = { + locale: locale, + dateFormat: format, + enableTime: false, + disableMobile: true, + onValueUpdate: () => this.onValueUpdate() + }; + + if (options.enableTime) { + Object.assign(defaultOptions, { + dateFormat: `${format} h:i`, + time_24hr: true + }); + } + + let mergedOptions = Object.assign({}, + defaultOptions, + options + ); + + if (this.picker) this.picker.destroy(); + this.picker = new Flatpickr(this.input, mergedOptions); + } + + onValueUpdate() { + let date = null; + + if (this.picker.selectedDates.length) + date = this.picker.selectedDates[0]; + + super.field = fixDate(date, -1); + this.$.$applyAsync(); + } + + $onDestroy() { + this.picker.destroy(); + } +} +DatePicker.$inject = ['$element', '$scope', '$compile', '$translate']; + +ngModule.vnComponent('vnDatePicker', { + controller: DatePicker, + bindings: { + options: ' { + let $filter; + let $element; + let $ctrl; + let today; + + beforeEach(angular.mock.module('vnCore', $translateProvider => { + $translateProvider.translations('en', {}); + })); + + beforeEach(angular.mock.inject(($compile, $rootScope, _$filter_) => { + $filter = _$filter_; + + $element = $compile(``)($rootScope); + $ctrl = $element.controller('vnDatePicker'); + + today = new Date(); + today.setUTCHours(0, 0, 0, 0); + })); + + afterEach(() => { + $element.remove(); + }); + + describe('field() setter', () => { + it(`should display the formated the date`, () => { + $ctrl.field = today; + + let displayed = $filter('dateTime')(today, 'yyyy-MM-dd'); + + expect($ctrl.value).toEqual(displayed); + }); + }); + + describe('options() setter', () => { + it(`should display the date with the new format`, () => { + $ctrl.options = {dateFormat: 'Y-m'}; + $ctrl.field = today; + + let displayed = $filter('dateTime')(today, 'yyyy-MM'); + + expect($ctrl.value).toEqual(displayed); + }); + }); +}); diff --git a/front/core/components/date-picker/style.scss b/front/core/components/date-picker/style.scss index d33f27b5d..6af4580f6 100644 --- a/front/core/components/date-picker/style.scss +++ b/front/core/components/date-picker/style.scss @@ -1,24 +1,5 @@ @import "variables"; -vn-date-picker { - .mdl-chip__action { - position: absolute; - width: auto; - top: 0px; - right: -6px; - margin: 22px 0px; - background-color: white; - } - .mdl-textfield { - width: 100%; - } - .material-icons { - font-size: 18px; - float: right; - margin-right: 5px; - } -} - .flatpickr-months .flatpickr-month, .flatpickr-weekdays, span.flatpickr-weekday { diff --git a/front/core/components/drop-down/drop-down.js b/front/core/components/drop-down/drop-down.js index 8422a60de..182ea49e0 100755 --- a/front/core/components/drop-down/drop-down.js +++ b/front/core/components/drop-down/drop-down.js @@ -194,10 +194,12 @@ export default class DropDown extends Component { this.document.addEventListener('keydown', this.docKeyDownHandler); this.$.list.scrollTop = 0; this.$.input.focus(); + this.emit('open'); } onClose() { this.document.removeEventListener('keydown', this.docKeyDownHandler); + this.emit('close'); } onClearClick() { diff --git a/front/core/components/field/index.html b/front/core/components/field/index.html index a2401ee4f..5e27c1fb3 100644 --- a/front/core/components/field/index.html +++ b/front/core/components/field/index.html @@ -5,9 +5,7 @@
-
- -
+