diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index f507d43de..f0d726ed6 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -394,11 +394,18 @@ export default { intrastadCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Intrastat"]', originCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Origin"]', buyerCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Buyer"]', + densityCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Density"]', + openAdvancedSearchButton: 'vn-searchbar .append vn-icon[icon="arrow_drop_down"]', + advancedSearchItemType: 'vn-item-search-panel vn-autocomplete[ng-model="filter.typeFk"]', + advancedSearchButton: 'vn-item-search-panel button[type=submit]', + advancedSmartTableButton: 'vn-item-index vn-button[icon="search"]', + advancedSmartTableGrouping: 'vn-item-index vn-textfield[name=grouping]', weightByPieceCheckbox: '.vn-popover.shown vn-horizontal:nth-child(3) > vn-check[label="Weight/Piece"]', saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button' }, itemFixedPrice: { add: 'vn-fixed-price vn-icon-button[icon="add_circle"]', + firstItemID: 'vn-fixed-price tr:nth-child(2) vn-autocomplete[ng-model="price.itemFk"]', fourthFixedPrice: 'vn-fixed-price tr:nth-child(5)', fourthItemID: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.itemFk"]', fourthWarehouse: 'vn-fixed-price tr:nth-child(5) vn-autocomplete[ng-model="price.warehouseFk"]', @@ -408,7 +415,8 @@ export default { fourthMinPrice: 'vn-fixed-price tr:nth-child(5) > td:nth-child(6) > vn-input-number[ng-model="price.minPrice"]', fourthStarted: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.started"]', fourthEnded: 'vn-fixed-price tr:nth-child(5) vn-date-picker[ng-model="price.ended"]', - fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]' + fourthDeleteIcon: 'vn-fixed-price tr:nth-child(5) > td:nth-child(9) > vn-icon-button[icon="delete"]', + orderColumnId: 'vn-fixed-price th[field="itemFk"]' }, itemCreateView: { temporalName: 'vn-item-create vn-textfield[ng-model="$ctrl.item.provisionalName"]', diff --git a/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js new file mode 100644 index 000000000..4fc280209 --- /dev/null +++ b/e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js @@ -0,0 +1,77 @@ +import selectors from '../../helpers/selectors.js'; +import getBrowser from '../../helpers/puppeteer'; + +describe('SmartTable SearchBar integration', () => { + let browser; + let page; + beforeAll(async() => { + browser = await getBrowser(); + page = browser.page; + await page.loginAndModule('salesPerson', 'item'); + await page.waitToClick(selectors.globalItems.searchButton); + }); + + afterAll(async() => { + await browser.close(); + }); + + describe('as filters', () => { + it('should search by type in searchBar', async() => { + await page.waitToClick(selectors.itemsIndex.openAdvancedSearchButton); + await page.autocompleteSearch(selectors.itemsIndex.advancedSearchItemType, 'Anthurium'); + await page.waitToClick(selectors.itemsIndex.advancedSearchButton); + await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3); + }); + + it('should reload page and have same results', async() => { + await page.reload({ + waitUntil: 'networkidle2' + }); + + await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 3); + }); + + it('should search by grouping in smartTable', async() => { + await page.waitToClick(selectors.itemsIndex.advancedSmartTableButton); + await page.write(selectors.itemsIndex.advancedSmartTableGrouping, '1'); + await page.keyboard.press('Enter'); + await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2); + }); + + it('should now reload page and have same results', async() => { + await page.reload({ + waitUntil: 'networkidle2' + }); + + await page.waitForNumberOfElements(selectors.itemsIndex.searchResult, 2); + }); + }); + + describe('as orders', () => { + it('should order by first id', async() => { + await page.loginAndModule('developer', 'item'); + await page.accessToSection('item.fixedPrice'); + await page.doSearch(); + + const result = await page.waitToGetProperty(selectors.itemFixedPrice.firstItemID, 'value'); + + expect(result).toEqual('1'); + }); + + it('should order by last id', async() => { + await page.waitToClick(selectors.itemFixedPrice.orderColumnId); + const result = await page.waitToGetProperty(selectors.itemFixedPrice.firstItemID, 'value'); + + expect(result).toEqual('13'); + }); + + it('should reload page and have same order', async() => { + await page.reload({ + waitUntil: 'networkidle2' + }); + const result = await page.waitToGetProperty(selectors.itemFixedPrice.firstItemID, 'value'); + + expect(result).toEqual('13'); + }); + }); +}); diff --git a/front/core/components/crud-model/crud-model.js b/front/core/components/crud-model/crud-model.js index 4994e1547..1095985dc 100644 --- a/front/core/components/crud-model/crud-model.js +++ b/front/core/components/crud-model/crud-model.js @@ -99,6 +99,18 @@ export default class CrudModel extends ModelProxy { return this.refresh(); } + /** + * Applies a new filter to the model. + * + * @param {Object} params Custom parameters + * @return {Promise} The request promise + */ + + applyParams(params) { + this.userParams = params; + return this.refresh(); + } + removeFilter() { return this.applyFilter(null, null); } diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index 89b5d7df6..10ec1f608 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -139,8 +139,12 @@ export default class Searchbar extends Component { } removeParam(index) { + const field = this.params[index].key; + this.filterSanitizer(field); + this.params.splice(index, 1); - this.doSearch(this.fromBar(), 'bar'); + this.toRemove = field; + this.doSearch(this.fromBar(), 'removeBar'); } fromBar() { @@ -163,7 +167,7 @@ export default class Searchbar extends Component { let keys = Object.keys(filter); keys.forEach(key => { - if (key == 'search') return; + if (key == 'search' || key == 'tableQ' || key == 'tableOrder') return; let value = filter[key]; let chip; @@ -198,6 +202,7 @@ export default class Searchbar extends Component { let promise = this.onSearch({$params: filter}); promise = promise || this.$q.resolve(); promise.then(data => this.onFilter(filter, source, data)); + this.toBar(filter); } onFilter(filter, source, data) { @@ -238,8 +243,11 @@ export default class Searchbar extends Component { } else { state = this.searchState; - if (filter) + if (filter) { + if (this.tableQ) + filter.tableQ = this.tableQ; params = {q: JSON.stringify(filter)}; + } if (this.$state.is(state)) opts = {location: 'replace'}; } @@ -247,6 +255,12 @@ export default class Searchbar extends Component { this.filter = filter; + if (source == 'removeBar') { + delete params[this.toRemove]; + delete this.model.userParams[this.toRemove]; + this.model.refresh(); + } + if (!filter && this.model) this.model.clear(); if (source != 'state') @@ -269,9 +283,14 @@ export default class Searchbar extends Component { this.model.clear(); return; } + if (Object.keys(filter).length === 0) { + this.filterSanitizer('search'); + if (this.model.userParams) + delete this.model.userParams['search']; + } let where = null; - let params = null; + let params = {}; if (this.exprBuilder) { where = buildFilter(filter, @@ -283,9 +302,89 @@ export default class Searchbar extends Component { params = this.fetchParams({$params: params}); } + this.tableQ = null; + + const hasParams = this.$params.q && Object.keys(JSON.parse(this.$params.q)).length; + if (hasParams) { + const stateFilter = JSON.parse(this.$params.q); + for (let param in stateFilter) { + if (param != 'tableQ' && param != 'orderQ') + this.filterSanitizer(param); + } + + for (let param in this.suggestedFilter) { + this.filterSanitizer(param); + delete stateFilter[param]; + } + + this.tableQ = stateFilter.tableQ; + for (let param in stateFilter.tableQ) + params[param] = stateFilter.tableQ[param]; + + Object.assign(stateFilter, params); + return this.model.applyParams(params) + .then(() => this.model.data); + } + return this.model.applyFilter(where ? {where} : null, params) .then(() => this.model.data); } + + filterSanitizer(field) { + if (!field) return; + const userFilter = this.model.userFilter; + const userParams = this.model.userParams; + const where = userFilter && userFilter.where; + + if (this.model.userParams) + delete this.model.userParams[field]; + + if (this.exprBuilder) { + const param = this.exprBuilder({ + param: field, + value: null + }); + if (param) [field] = Object.keys(param); + } + + if (!where) return; + + const whereKeys = Object.keys(where); + for (let key of whereKeys) { + removeProp(where, field, key); + + if (Object.keys(where).length == 0) + delete userFilter.where; + } + + function removeProp(obj, targetProp, prop) { + if (prop == targetProp) + delete obj[prop]; + + if (prop === 'and' || prop === 'or' && obj[prop]) { + const arrayCopy = obj[prop].slice(); + for (let param of arrayCopy) { + const [key] = Object.keys(param); + const index = obj[prop].findIndex(param => { + return Object.keys(param)[0] == key; + }); + if (key == targetProp) + obj[prop].splice(index, 1); + + if (param[key] instanceof Array) + removeProp(param, field, key); + + if (Object.keys(param).length == 0) + obj[prop].splice(index, 1); + } + + if (obj[prop].length == 0) + delete obj[prop]; + } + } + + return {userFilter, userParams}; + } } ngModule.vnComponent('vnSearchbar', { diff --git a/front/core/components/searchbar/searchbar.spec.js b/front/core/components/searchbar/searchbar.spec.js index e4f58d294..ed8fd9d07 100644 --- a/front/core/components/searchbar/searchbar.spec.js +++ b/front/core/components/searchbar/searchbar.spec.js @@ -6,7 +6,7 @@ describe('Component vnSearchbar', () => { let $state; let $params; let $scope; - let filter = {id: 1, search: 'needle'}; + const filter = {id: 1, search: 'needle'}; beforeEach(ngModule('vnCore', $stateProvider => { $stateProvider @@ -70,8 +70,8 @@ describe('Component vnSearchbar', () => { describe('filter() setter', () => { it(`should update the bar params and search`, () => { - let withoutHours = new Date(2000, 1, 1); - let withHours = new Date(withoutHours.getTime()); + const withoutHours = new Date(2000, 1, 1); + const withHours = new Date(withoutHours.getTime()); withHours.setHours(12, 30, 15, 10); controller.filter = { @@ -83,8 +83,8 @@ describe('Component vnSearchbar', () => { myObjectProp: {myProp: 1} }; - let chips = {}; - for (let param of controller.params || []) + const chips = {}; + for (const param of controller.params || []) chips[param.key] = param.chip; expect(controller.searchString).toBe('needle'); @@ -172,13 +172,22 @@ describe('Component vnSearchbar', () => { describe('removeParam()', () => { it(`should remove the parameter from the filter`, () => { jest.spyOn(controller, 'doSearch'); + controller.model = { + refresh: jest.fn(), + userParams: { + id: 1 + } + }; + + controller.model.applyParams = jest.fn().mockReturnValue(Promise.resolve()); + jest.spyOn(controller.model, 'applyParams'); controller.filter = filter; controller.removeParam(0); expect(controller.doSearch).toHaveBeenCalledWith({ search: 'needle' - }, 'bar'); + }, 'removeBar'); }); }); @@ -199,7 +208,7 @@ describe('Component vnSearchbar', () => { it(`should go to the summary state when one result`, () => { jest.spyOn($state, 'go'); - let data = [{id: 1}]; + const data = [{id: 1}]; controller.baseState = 'foo'; controller.onFilter(filter, 'any', data); @@ -214,7 +223,7 @@ describe('Component vnSearchbar', () => { $scope.$apply(); jest.spyOn($state, 'go'); - let data = [{id: 1}]; + const data = [{id: 1}]; controller.baseState = 'foo'; controller.onFilter(filter, 'any', data); @@ -229,7 +238,7 @@ describe('Component vnSearchbar', () => { $scope.$apply(); jest.spyOn($state, 'go'); - let data = [{id: 1}]; + const data = [{id: 1}]; controller.baseState = 'foo'; controller.onFilter(filter, 'any', data); @@ -247,7 +256,7 @@ describe('Component vnSearchbar', () => { controller.onFilter(filter, 'any'); $scope.$apply(); - let queryParams = {q: JSON.stringify(filter)}; + const queryParams = {q: JSON.stringify(filter)}; expect($state.go).toHaveBeenCalledWith('search.state', queryParams, undefined); expect(controller.filter).toEqual(filter); diff --git a/front/core/components/smart-table/index.html b/front/core/components/smart-table/index.html index f26a6b4a2..752019313 100644 --- a/front/core/components/smart-table/index.html +++ b/front/core/components/smart-table/index.html @@ -103,3 +103,4 @@ + diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index 9e6e7009c..8d2c3c153 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -15,9 +15,17 @@ export default class SmartTable extends Component { this.$inputsScope; this.columns = []; this.autoSave = false; + this.autoState = true; this.transclude(); } + $onChanges() { + if (this.model) { + this.defaultFilter(); + this.defaultOrder(); + } + } + $onDestroy() { const styleElement = document.querySelector('style[id="smart-table"]'); if (this.$.css && styleElement) @@ -47,10 +55,8 @@ export default class SmartTable extends Component { set model(value) { this._model = value; - if (value) { + if (value) this.$.model = value; - this.defaultOrder(); - } } getDefaultViewConfig() { @@ -160,8 +166,36 @@ export default class SmartTable extends Component { } } + defaultFilter() { + if (this.disabledTableFilter || !this.$params.q) return; + + const stateFilter = JSON.parse(this.$params.q).tableQ; + if (!stateFilter || !this.exprBuilder) return; + + const columns = this.columns.map(column => column.field); + + this.displaySearch(); + if (!this.$inputsScope.searchProps) + this.$inputsScope.searchProps = {}; + + for (let param in stateFilter) { + if (columns.includes(param)) { + const whereParams = {[param]: stateFilter[param]}; + Object.assign(this.$inputsScope.searchProps, whereParams); + this.addFilter(param, stateFilter[param]); + } + } + } + defaultOrder() { - const order = this.model.order; + if (this.disabledTableOrder) return; + + let stateOrder; + if (this.$params.q) + stateOrder = JSON.parse(this.$params.q).tableOrder; + + const order = stateOrder ? stateOrder : this.model.order; + if (!order) return; const orderFields = order.split(', '); @@ -195,6 +229,9 @@ export default class SmartTable extends Component { this.setPriority(column.element, priority); } } + + this.model.order = order; + this.refresh(); } registerColumns() { @@ -395,28 +432,54 @@ export default class SmartTable extends Component { } searchByColumn(field) { - const searchCriteria = this.$inputsScope.searchProps[field]; - const emptySearch = searchCriteria === '' || searchCriteria == null; - const filters = this.filterSanitizer(field); if (filters && filters.userFilter) this.model.userFilter = filters.userFilter; - if (!emptySearch) - this.addFilter(field, this.$inputsScope.searchProps[field]); - else this.model.refresh(); + this.addFilter(field, this.$inputsScope.searchProps[field]); + } + + searchPropsSanitizer() { + if (!this.$inputsScope || !this.$inputsScope.searchProps) return null; + let searchProps = this.$inputsScope.searchProps; + const searchPropsArray = Object.entries(searchProps); + searchProps = searchPropsArray.filter( + ([key, value]) => value && value != '' + ); + + return Object.fromEntries(searchProps); } addFilter(field, value) { - let where = {[field]: value}; + if (value == '') value = null; - if (this.exprBuilder) { - where = buildFilter(where, (param, value) => - this.exprBuilder({param, value}) - ); + let stateFilter = {tableQ: {}}; + if (this.$params.q) { + stateFilter = JSON.parse(this.$params.q); + if (!stateFilter.tableQ) + stateFilter.tableQ = {}; + delete stateFilter.tableQ[field]; } - this.model.addFilter({where}); + const whereParams = {[field]: value}; + if (value) { + let where = {[field]: value}; + if (this.exprBuilder) { + where = buildFilter(whereParams, (param, value) => + this.exprBuilder({param, value}) + ); + } + this.model.addFilter({where}); + } + + const searchProps = this.searchPropsSanitizer(); + + Object.assign(stateFilter.tableQ, searchProps); + + const params = {q: JSON.stringify(stateFilter)}; + + this.$state.go(this.$state.current.name, params, {location: 'replace'}); + this.refresh(); } applySort() { @@ -426,7 +489,18 @@ export default class SmartTable extends Component { if (order) this.model.order = order; - this.model.refresh(); + let stateFilter = {tableOrder: {}}; + if (this.$params.q) { + stateFilter = JSON.parse(this.$params.q); + if (!stateFilter.tableOrder) + stateFilter.tableOrder = {}; + } + + stateFilter.tableOrder = order; + + const params = {q: JSON.stringify(stateFilter)}; + this.$state.go(this.$state.current.name, params, {location: 'replace'}); + this.refresh(); } filterSanitizer(field) { @@ -535,6 +609,8 @@ ngModule.vnComponent('smartTable', { autoSave: ' { $httpBackend = _$httpBackend_; $element = $compile(``)($rootScope); controller = $element.controller('smartTable'); + controller.model = { + refresh: jest.fn().mockReturnValue(new Promise(resolve => resolve())), + addFilter: jest.fn(), + userParams: {} + }; })); afterEach(() => { @@ -83,7 +88,7 @@ describe('Component smartTable', () => { describe('defaultOrder', () => { it('should insert a new object to the controller sortCriteria with a sortType value of "ASC"', () => { const element = document.createElement('div'); - controller.model = {order: 'id'}; + controller.model.order = 'id'; controller.columns = [ {field: 'id', element: element}, {field: 'test1', element: element}, @@ -101,7 +106,8 @@ describe('Component smartTable', () => { it('should add new entries to the controller sortCriteria with a sortType values of "ASC" and "DESC"', () => { const element = document.createElement('div'); - controller.model = {order: 'test1, id DESC'}; + controller.model.order = 'test1, id DESC'; + controller.columns = [ {field: 'id', element: element}, {field: 'test1', element: element}, @@ -125,8 +131,6 @@ describe('Component smartTable', () => { describe('addFilter()', () => { it('should call the model addFilter() with a basic where filter if exprBuilder() was not received', () => { - controller.model = {addFilter: jest.fn()}; - controller.addFilter('myField', 'myValue'); const expectedFilter = { @@ -140,7 +144,6 @@ describe('Component smartTable', () => { it('should call the model addFilter() with a built where filter resultant of exprBuilder()', () => { controller.exprBuilder = jest.fn().mockReturnValue({builtField: 'builtValue'}); - controller.model = {addFilter: jest.fn()}; controller.addFilter('myField', 'myValue'); @@ -155,35 +158,48 @@ describe('Component smartTable', () => { }); describe('applySort()', () => { - it('should call the model refresh() without making changes on the model order', () => { - controller.model = {refresh: jest.fn()}; + it('should call the $state go and model refresh without making changes on the model order', () => { + controller.$state = { + go: jest.fn(), + current: { + name: 'section' + } + }; + jest.spyOn(controller, 'refresh'); controller.applySort(); expect(controller.model.order).toBeUndefined(); - expect(controller.model.refresh).toHaveBeenCalled(); + expect(controller.$state.go).toHaveBeenCalled(); + expect(controller.refresh).toHaveBeenCalled(); }); - it('should call the model.refresh() after setting model order according to the controller sortCriteria', () => { - controller.model = {refresh: jest.fn()}; + it('should call the $state go and model refresh after setting model order according to the controller sortCriteria', () => { const orderBy = {field: 'myField', sortType: 'ASC'}; + controller.$state = { + go: jest.fn(), + current: { + name: 'section' + } + }; + jest.spyOn(controller, 'refresh'); + controller.sortCriteria = [orderBy]; controller.applySort(); expect(controller.model.order).toEqual(`${orderBy.field} ${orderBy.sortType}`); - expect(controller.model.refresh).toHaveBeenCalled(); + expect(controller.$state.go).toHaveBeenCalled(); + expect(controller.refresh).toHaveBeenCalled(); }); }); describe('filterSanitizer()', () => { it('should remove the where filter after leaving no fields in it', () => { - controller.model = { - userFilter: { - where: {fieldToRemove: 'valueToRemove'} - }, - userParams: {} + controller.model.userFilter = { + where: {fieldToRemove: 'valueToRemove'} }; + controller.model.userParams = {}; const result = controller.filterSanitizer('fieldToRemove'); @@ -193,23 +209,21 @@ describe('Component smartTable', () => { }); it('should remove the where filter after leaving no fields and "empty ands/ors" in it', () => { - controller.model = { - userFilter: { - where: { - and: [ - {aFieldToRemove: 'aValueToRemove'}, - {aFieldToRemove: 'aValueToRemove'}, - { - or: [ - {aFieldToRemove: 'aValueToRemove'}, - {aFieldToRemove: 'aValueToRemove'}, - ] - } - ] - } - }, - userParams: {} - }; + controller.model.userFilter = { + where: { + and: [ + {aFieldToRemove: 'aValueToRemove'}, + {aFieldToRemove: 'aValueToRemove'}, + { + or: [ + {aFieldToRemove: 'aValueToRemove'}, + {aFieldToRemove: 'aValueToRemove'}, + ] + } + ] + } + }, + controller.model.userParams = {}; const result = controller.filterSanitizer('aFieldToRemove'); @@ -219,24 +233,22 @@ describe('Component smartTable', () => { }); it('should not remove the where filter after leaving no empty "ands/ors" in it', () => { - controller.model = { - userFilter: { - where: { - and: [ - {aFieldToRemove: 'aValueToRemove'}, - {aFieldToRemove: 'aValueToRemove'}, - { - or: [ - {aFieldToRemove: 'aValueToRemove'}, - {aFieldToRemove: 'aValueToRemove'}, - ] - } - ], - or: [{dontKillMe: 'thanks'}] - } - }, - userParams: {} + controller.model.userFilter = { + where: { + and: [ + {aFieldToRemove: 'aValueToRemove'}, + {aFieldToRemove: 'aValueToRemove'}, + { + or: [ + {aFieldToRemove: 'aValueToRemove'}, + {aFieldToRemove: 'aValueToRemove'}, + ] + } + ], + or: [{dontKillMe: 'thanks'}] + } }; + controller.model.userParams = {}; const result = controller.filterSanitizer('aFieldToRemove'); @@ -249,7 +261,7 @@ describe('Component smartTable', () => { describe('saveAll()', () => { it('should throw an error if there are no changes to save in the model', () => { jest.spyOn(controller.vnApp, 'showError'); - controller.model = {isChanged: false}; + controller.model.isChanged = false; controller.saveAll(); expect(controller.vnApp.showError).toHaveBeenCalledWith('No changes to save'); @@ -258,10 +270,8 @@ describe('Component smartTable', () => { it('should call the showSuccess() if there are changes to save in the model', done => { jest.spyOn(controller.vnApp, 'showSuccess'); - controller.model = { - save: jest.fn().mockReturnValue(Promise.resolve()), - isChanged: true - }; + controller.model.save = jest.fn().mockReturnValue(Promise.resolve()); + controller.model.isChanged = true; controller.saveAll().then(() => { expect(controller.vnApp.showSuccess).toHaveBeenCalledWith('Data saved!'); @@ -269,4 +279,43 @@ describe('Component smartTable', () => { }).catch(done.fail); }); }); + + describe('defaultFilter()', () => { + it('should call model refresh and model addFilter with filter', () => { + controller.exprBuilder = jest.fn().mockReturnValue({builtField: 'builtValue'}); + + controller.$params = { + q: '{"tableQ": {"fieldName":"value"}}' + }; + controller.columns = [ + {field: 'fieldName'} + ]; + controller.$inputsScope = { + searchProps: {} + }; + jest.spyOn(controller, 'refresh'); + + controller.defaultFilter(); + + expect(controller.model.addFilter).toHaveBeenCalled(); + expect(controller.refresh).toHaveBeenCalled(); + }); + }); + + describe('searchPropsSanitizer()', () => { + it('should searchProps sanitize', () => { + controller.$inputsScope = { + searchProps: { + filterOne: '1', + filterTwo: '' + } + }; + const searchPropsExpected = { + filterOne: '1' + }; + const newSearchProps = controller.searchPropsSanitizer(); + + expect(newSearchProps).toEqual(searchPropsExpected); + }); + }); }); diff --git a/modules/claim/front/routes.json b/modules/claim/front/routes.json index d02ea6f6c..a8b958c5f 100644 --- a/modules/claim/front/routes.json +++ b/modules/claim/front/routes.json @@ -73,7 +73,7 @@ { "url": "/note", "state": "claim.card.note", - "component": "ui-view", + "component": "ui-view", "abstract": true, "acl": ["salesPerson"] }, @@ -105,7 +105,7 @@ "acl": ["claimManager"] }, { - "url": "/action", + "url": "/action?q", "state": "claim.card.action", "component": "vn-claim-action", "description": "Action", @@ -131,4 +131,4 @@ "acl": ["claimManager"] } ] -} \ No newline at end of file +} diff --git a/modules/client/front/routes.json b/modules/client/front/routes.json index c7462e46c..406ca07d7 100644 --- a/modules/client/front/routes.json +++ b/modules/client/front/routes.json @@ -20,7 +20,7 @@ {"state": "client.card.credit.index", "icon": "credit_card"}, {"state": "client.card.greuge.index", "icon": "work"}, {"state": "client.card.balance.index", "icon": "icon-invoice"}, - {"state": "client.card.recovery.index", "icon": "icon-recovery"}, + {"state": "client.card.recovery.index", "icon": "icon-recovery"}, {"state": "client.card.webAccess", "icon": "cloud"}, {"state": "client.card.log", "icon": "history"}, { @@ -37,7 +37,7 @@ {"state": "client.card.unpaid", "icon": "icon-defaulter"} ] } - ] + ] }, "keybindings": [ {"key": "c", "state": "client.index"} @@ -147,7 +147,7 @@ { "url": "/note", "state": "client.card.note", - "component": "ui-view", + "component": "ui-view", "abstract": true }, { @@ -236,7 +236,7 @@ "client": "$ctrl.client" } }, - { + { "url": "/create?payed&companyFk&bankFk&payedAmount", "state": "client.card.balance.create", "component": "vn-client-balance-create", @@ -406,13 +406,13 @@ } }, { - "url": "/defaulter", + "url": "/defaulter?q", "state": "client.defaulter", "component": "vn-client-defaulter", "description": "Defaulter" }, { - "url" : "/notification", + "url" : "/notification?q", "state": "client.notification", "component": "vn-client-notification", "description": "Notifications" @@ -424,7 +424,7 @@ "description": "Unpaid" }, { - "url": "/extended-list", + "url": "/extended-list?q", "state": "client.extendedList", "component": "vn-client-extended-list", "description": "Extended list" diff --git a/modules/item/front/fixed-price/index.html b/modules/item/front/fixed-price/index.html index 8127a76dc..9498bf96f 100644 --- a/modules/item/front/fixed-price/index.html +++ b/modules/item/front/fixed-price/index.html @@ -23,9 +23,9 @@
- @@ -34,18 +34,18 @@ - - -
Item ID + Description Warehouse P.P.U. P.P.P. @@ -170,7 +170,7 @@ - + - \ No newline at end of file + diff --git a/modules/item/front/fixed-price/index.js b/modules/item/front/fixed-price/index.js index b84c2cc2d..89ce0b172 100644 --- a/modules/item/front/fixed-price/index.js +++ b/modules/item/front/fixed-price/index.js @@ -12,14 +12,6 @@ export default class Controller extends Section { }, defaultSearch: true, columns: [ - { - field: 'itemName', - autocomplete: { - url: 'Items', - showField: 'name', - valueField: 'id' - } - }, { field: 'warehouseFk', autocomplete: { @@ -105,8 +97,8 @@ export default class Controller extends Section { exprBuilder(param, value) { switch (param) { - case 'itemName': - return {'i.id': value}; + case 'name': + return {'i.name': {like: `%${value}%`}}; case 'itemFk': case 'warehouseFk': case 'rate2': diff --git a/modules/monitor/front/index/clients/index.html b/modules/monitor/front/index/clients/index.html index eafc2256e..381c0e1ae 100644 --- a/modules/monitor/front/index/clients/index.html +++ b/modules/monitor/front/index/clients/index.html @@ -19,22 +19,24 @@ - @@ -100,9 +102,9 @@ - - \ No newline at end of file + diff --git a/modules/route/front/routes.json b/modules/route/front/routes.json index f5e7d9ae8..75e1fdc57 100644 --- a/modules/route/front/routes.json +++ b/modules/route/front/routes.json @@ -39,7 +39,7 @@ "abstract": true, "component": "vn-route-card" }, { - "url": "/agency-term", + "url": "/agency-term?q", "abstract": true, "state": "route.agencyTerm", "component": "ui-view" @@ -49,12 +49,12 @@ "component": "vn-agency-term-index", "description": "Autonomous", "acl": ["administrative"] - },{ + },{ "url": "/createInvoiceIn?q", "state": "route.agencyTerm.createInvoiceIn", "component": "vn-agency-term-create-invoice-in", "description": "File management", - "params": { + "params": { "route": "$ctrl.route" }, "acl": ["administrative"] @@ -92,4 +92,4 @@ "acl": ["delivery"] } ] -} \ No newline at end of file +}