From c9fd48b0cde98f46ed289abeea7d31e93345386b Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Wed, 19 Feb 2020 11:57:39 +0100 Subject: [PATCH] 2112 - Catalog improvements --- e2e/helpers/selectors.js | 6 +- .../front/catalog-search-panel/index.html | 9 +- modules/order/front/catalog/index.html | 26 ++++- modules/order/front/catalog/index.js | 82 ++++++++++++++-- modules/order/front/catalog/index.spec.js | 97 ++++++++++++++----- modules/order/front/prices-popover/index.js | 24 ----- modules/order/front/routes.json | 2 +- 7 files changed, 176 insertions(+), 70 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 42480dafd..451aaf7f7 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -620,9 +620,9 @@ export default { orderCatalog: { plantRealmButton: 'vn-order-catalog > vn-side-menu vn-icon[icon="icon-plant"]', type: 'vn-autocomplete[data="$ctrl.itemTypes"]', - itemId: 'vn-order-catalog > vn-side-menu vn-textfield[ng-model="$ctrl.itemId"]', - itemTagValue: 'vn-order-catalog > vn-side-menu vn-datalist[ng-model="$ctrl.value"]', - openTagSearch: 'vn-order-catalog > vn-side-menu > div > vn-vertical > vn-datalist[ng-model="$ctrl.value"] .append i', + itemId: 'vn-order-catalog > vn-side-menu vn-textfield[vn-id="itemId"]', + itemTagValue: 'vn-order-catalog > vn-side-menu vn-datalist[vn-id="search"]', + openTagSearch: 'vn-order-catalog > vn-side-menu > div > vn-vertical > vn-datalist[vn-id="search"] .append i', tag: 'vn-order-catalog-search-panel vn-autocomplete[ng-model="filter.tagFk"]', tagValue: 'vn-order-catalog-search-panel vn-textfield[ng-model="filter.value"]', searchTagButton: 'vn-order-catalog-search-panel button[type=submit]', diff --git a/modules/order/front/catalog-search-panel/index.html b/modules/order/front/catalog-search-panel/index.html index 3bd0ba3e2..d32ecaafa 100644 --- a/modules/order/front/catalog-search-panel/index.html +++ b/modules/order/front/catalog-search-panel/index.html @@ -1,13 +1,15 @@
-
+ + value-field="id" + required="true"> {{name}} @@ -15,7 +17,8 @@ + ng-model="filter.value" + required="true"> diff --git a/modules/order/front/catalog/index.html b/modules/order/front/catalog/index.html index 37767e81b..7131d6a6e 100644 --- a/modules/order/front/catalog/index.html +++ b/modules/order/front/catalog/index.html @@ -77,10 +77,9 @@
- + label="Item id"> @@ -89,7 +88,6 @@
+ + Id: {{$ctrl.itemId}} + - {{::tag.value}} +
+ + + {{::tag.tagSelection.name}} + + : + + + "{{::tag.value}}" + +
\ No newline at end of file diff --git a/modules/order/front/catalog/index.js b/modules/order/front/catalog/index.js index ff14c592b..87dff29e2 100644 --- a/modules/order/front/catalog/index.js +++ b/modules/order/front/catalog/index.js @@ -10,7 +10,7 @@ class Controller { this.$compile = $compile; this.$transitions = $transitions; this.itemTypes = []; - this.tags = []; + this._tags = []; // Static autocomplete data this.orderWays = [ @@ -52,11 +52,17 @@ class Controller { if (!value) return; this.$.$applyAsync(() => { + if (this.$stateParams.itemId) + this.itemId = parseInt(this.$stateParams.itemId); + if (this.$stateParams.categoryId) - this.categoryId = this.$stateParams.categoryId; + this.categoryId = parseInt(this.$stateParams.categoryId); if (this.$stateParams.typeId) - this.typeId = this.$stateParams.typeId; + this.typeId = parseInt(this.$stateParams.typeId); + + if (this.$stateParams.tags) + this.tags = JSON.parse(this.$stateParams.tags); }); } @@ -109,6 +115,30 @@ class Controller { this.applyFilters(); } + get itemId() { + return this._itemId; + } + + set itemId(value) { + this._itemId = value; + + this.updateStateParams(); + this.applyFilters(); + } + + get tags() { + return this._tags; + } + + set tags(value) { + this._tags = value; + + this.updateStateParams(); + + if (value.length) + this.applyFilters(); + } + /** * Get order way ASC/DESC */ @@ -169,23 +199,36 @@ class Controller { this.itemTypes = res.data); } + /** + * Search by item id filter + * @param {object} event + */ onSearchById(event) { - const hasValue = this.tags.length > 0 || this.itemId || this.typeId; - if (event.key === 'Enter' && hasValue) - this.applyFilters(); + const value = this.$.itemId.value; + if (event.key === 'Enter' && value) { + this.itemId = value; + this.$.itemId.value = null; + } } + /** + * Search by tag value + * @param {object} event + */ onSearchByTag(event) { - if (event.key !== 'Enter' || !this.value) return; + const value = this.$.search.value; + if (event.key !== 'Enter' || !value) return; this.tags.push({ - value: this.value, + value: value, }); this.$.search.value = null; + this.updateStateParams(); this.applyFilters(); } remove(index) { this.tags.splice(index, 1); + this.updateStateParams(); if (this.tags.length >= 0 || this.itemId || this.typeId) this.applyFilters(); @@ -225,6 +268,7 @@ class Controller { onPanelSubmit(filter) { this.$.popover.hide(); this.tags.push(filter); + this.updateStateParams(); this.applyFilters(); } @@ -242,6 +286,28 @@ class Controller { params.typeId = this.typeId; else params.typeId = undefined; + if (this.itemId) + params.itemId = this.itemId; + else params.itemId = undefined; + + if (this.tags.length) { + const tags = []; + for (let tag of this.tags) { + const tagParam = {value: tag.value}; + + if (tag.tagSelection) { + tagParam.tagFk = tag.tagFk; + tagParam.tagSelection = { + name: tag.tagSelection.name + }; + } + + tags.push(tagParam); + } + + params.tags = JSON.stringify(tags); + } else params.tags = undefined; + this.$state.go(this.$state.current.name, params); } diff --git a/modules/order/front/catalog/index.spec.js b/modules/order/front/catalog/index.spec.js index 01da61800..e2d2d0aff 100644 --- a/modules/order/front/catalog/index.spec.js +++ b/modules/order/front/catalog/index.spec.js @@ -15,6 +15,7 @@ describe('Order', () => { $scope = $rootScope.$new(); $scope.model = crudModel; $scope.search = {}; + $scope.itemId = {}; $state = _$state_; $state.params.categoryId = 1; $state.params.typeId = 2; @@ -37,8 +38,9 @@ describe('Order', () => { describe('items() setter', () => { it(`should return an object with order params`, () => { - spyOn(controller, 'buildTagsFilter'); - spyOn(controller, 'buildOrderFilter').and.callThrough(); + jest.spyOn(controller, 'buildTagsFilter'); + jest.spyOn(controller, 'buildOrderFilter'); + const expectedResult = [{field: 'showOrder, price', name: 'Color and price'}]; const items = [{id: 1, name: 'My Item', tags: [ {tagFk: 4, name: 'Length'}, @@ -55,14 +57,16 @@ describe('Order', () => { describe('categoryId() setter', () => { it(`should set category property to null, call updateStateParams() method and not call applyFilters()`, () => { - spyOn(controller, 'updateStateParams'); + jest.spyOn(controller, 'updateStateParams'); + controller.categoryId = null; expect(controller.updateStateParams).toHaveBeenCalledWith(); }); it(`should set category property and then call updateStateParams() and applyFilters() methods`, () => { - spyOn(controller, 'updateStateParams'); + jest.spyOn(controller, 'updateStateParams'); + controller.categoryId = 2; expect(controller.updateStateParams).toHaveBeenCalledWith(); @@ -87,8 +91,9 @@ describe('Order', () => { describe('typeId() setter', () => { it(`should set type property to null, call updateStateParams() method and not call applyFilters()`, () => { - spyOn(controller, 'updateStateParams'); - spyOn(controller, 'applyFilters'); + jest.spyOn(controller, 'updateStateParams'); + jest.spyOn(controller, 'applyFilters'); + controller.typeId = null; expect(controller.updateStateParams).toHaveBeenCalledWith(); @@ -96,8 +101,9 @@ describe('Order', () => { }); it(`should set category property and then call updateStateParams() and applyFilters() methods`, () => { - spyOn(controller, 'updateStateParams'); - spyOn(controller, 'applyFilters'); + jest.spyOn(controller, 'updateStateParams'); + jest.spyOn(controller, 'applyFilters'); + controller.typeId = 2; expect(controller.updateStateParams).toHaveBeenCalledWith(); @@ -105,21 +111,46 @@ describe('Order', () => { }); }); + describe('itemId() setter', () => { + it(`should set itemId property and then call updateStateParams() and applyFilters() methods`, () => { + jest.spyOn(controller, 'updateStateParams'); + jest.spyOn(controller, 'applyFilters'); + + controller.itemId = 1; + + expect(controller.updateStateParams).toHaveBeenCalledWith(); + expect(controller.applyFilters).toHaveBeenCalledWith(); + }); + }); + + describe('tags() setter', () => { + it(`should set tags property and then call updateStateParams() and applyFilters() methods`, () => { + jest.spyOn(controller, 'updateStateParams'); + jest.spyOn(controller, 'applyFilters'); + + controller.tags = [{tagFk: 11, value: 'Brown'}]; + + expect(controller.updateStateParams).toHaveBeenCalledWith(); + expect(controller.applyFilters).toHaveBeenCalledWith(); + }); + }); + describe('onSearchByTag()', () => { it(`should not add a new tag if the event key code doesn't equals to 'Enter'`, () => { - spyOn(controller, 'applyFilters'); + jest.spyOn(controller, 'applyFilters'); + controller.order = {id: 4}; - controller.value = 'Color'; + controller.$.search.value = 'Brown'; controller.onSearchByTag({key: 'Tab'}); expect(controller.applyFilters).not.toHaveBeenCalledWith(); }); it(`should add a new tag if the event key code equals to 'Enter' an then call applyFilters()`, () => { - spyOn(controller, 'applyFilters'); - controller.order = {id: 4}; - controller.value = 'Color'; + jest.spyOn(controller, 'applyFilters'); + controller.order = {id: 4}; + controller.$.search.value = 'Brown'; controller.onSearchByTag({key: 'Enter'}); expect(controller.applyFilters).toHaveBeenCalledWith(); @@ -128,17 +159,18 @@ describe('Order', () => { describe('onSearchById()', () => { it(`should not filter by id if the event key code doesn't equals to 'Enter'`, () => { - spyOn(controller, 'applyFilters'); - controller.itemId = 1; + jest.spyOn(controller, 'applyFilters'); + + controller.$.itemId.value = 1; controller.onSearchById({key: 'Tab'}); expect(controller.applyFilters).not.toHaveBeenCalledWith(); }); it(`should filter by id if the event key code equals to 'Enter' an then call applyFilters()`, () => { - spyOn(controller, 'applyFilters'); - controller.itemId = 1; + jest.spyOn(controller, 'applyFilters'); + controller.$.itemId.value = 1; controller.onSearchById({key: 'Enter'}); expect(controller.applyFilters).toHaveBeenCalledWith(); @@ -147,14 +179,14 @@ describe('Order', () => { describe('applyFilters()', () => { it(`should call model applyFilter() method with a new filter`, () => { - let model = controller.$.model; - spyOn(model, 'applyFilter'); + jest.spyOn(controller.$.model, 'applyFilter'); + controller._categoryId = 2; controller._typeId = 4; controller.applyFilters(); - expect(model.applyFilter).toHaveBeenCalledWith( + expect(controller.$.model.applyFilter).toHaveBeenCalledWith( {where: {categoryFk: 2, typeFk: 4}}, {orderFk: 4, orderBy: controller.getOrderBy(), tags: []}); }); @@ -162,7 +194,8 @@ describe('Order', () => { describe('remove()', () => { it(`should remove a tag from tags property`, () => { - spyOn(controller, 'applyFilters'); + jest.spyOn(controller, 'applyFilters'); + controller.tags = [{tagFk: 1, value: 'Blue'}, {tagFk: 2, value: '70'}]; controller.remove(0); @@ -172,7 +205,8 @@ describe('Order', () => { }); it(`should remove a tag from tags property and call applyFilters() if there's no more tags`, () => { - spyOn(controller, 'applyFilters'); + jest.spyOn(controller, 'applyFilters'); + controller._categoryId = 1; controller._typeId = 1; controller.tags = [{tagFk: 1, value: 'Blue'}]; @@ -185,10 +219,19 @@ describe('Order', () => { describe('updateStateParams()', () => { it(`should call state go() method passing category and type state params`, () => { - spyOn(controller.$state, 'go'); + jest.spyOn(controller.$state, 'go'); + controller._categoryId = 2; controller._typeId = 4; - let result = {categoryId: 2, typeId: 4}; + controller._itemId = 1; + controller._tags = [ + {tagFk: 11, value: 'Precission', tagSelection: {name: 'Category'}} + ]; + const tags = JSON.stringify([{ + value: 'Precission', + tagFk: 11, tagSelection: {name: 'Category'}} + ]); + let result = {categoryId: 2, typeId: 4, itemId: 1, tags: tags}; controller.updateStateParams(); expect(controller.$state.go).toHaveBeenCalledWith('my.current.state', result); @@ -212,13 +255,15 @@ describe('Order', () => { describe('applyOrder()', () => { it(`should apply order param to model calling getOrderBy()`, () => { + jest.spyOn(controller, 'getOrderBy'); + jest.spyOn(controller.$.model, 'addFilter'); + controller.field = 'relevancy DESC, name'; controller.way = 'ASC'; controller._categoryId = 1; controller._typeId = 1; let expectedOrder = {orderBy: controller.getOrderBy()}; - spyOn(controller, 'getOrderBy').and.callThrough(); - spyOn(controller.$.model, 'addFilter'); + controller.applyOrder(); expect(controller.getOrderBy).toHaveBeenCalledWith(); diff --git a/modules/order/front/prices-popover/index.js b/modules/order/front/prices-popover/index.js index 2df8bea15..b732f2090 100644 --- a/modules/order/front/prices-popover/index.js +++ b/modules/order/front/prices-popover/index.js @@ -73,30 +73,6 @@ class Controller extends Component { addQuantity(price) { if (this.total + price.grouping <= this.max) price.quantity += price.grouping; - - this.validate(); - } - - validate() { - /* - this.$timeout(() => { - this.calculateTotal(); - let inputs = this.$element[0].querySelectorAll('vn-input-number[name="quantity"] div.infix:not(.validated)'); - - inputs.forEach(input => { - if (this.total > this.item.available) - input.classList.add('invalid'); - else - input.classList.remove('invalid'); - }); - let wrongInputs = this.$element[0].querySelectorAll('vn-input-number[name="quantity"] div.infix.invalid'); - - if (wrongInputs.length > 0) - this.$element[0].querySelector('vn-vertical.prices').classList.add('invalid'); - else - this.$element[0].querySelector('vn-vertical.prices').classList.remove('invalid'); - }); - */ } getFilledLines() { diff --git a/modules/order/front/routes.json b/modules/order/front/routes.json index 789870fd1..b607aef9d 100644 --- a/modules/order/front/routes.json +++ b/modules/order/front/routes.json @@ -41,7 +41,7 @@ "order": "$ctrl.order" } }, { - "url": "/catalog?categoryId&typeId", + "url": "/catalog?categoryId&typeId&itemId&tags", "state": "order.card.catalog", "component": "vn-order-catalog", "description": "Catalog",