From 8082e3071ad2e35d163cff01838372a4682dbde7 Mon Sep 17 00:00:00 2001 From: alexm Date: Tue, 27 Sep 2022 15:17:54 +0200 Subject: [PATCH 1/6] try --- front/core/components/searchbar/searchbar.js | 82 +++++++++++++++++++- front/core/components/smart-table/index.html | 4 + front/core/components/smart-table/index.js | 82 +++++++++++++++++--- 3 files changed, 152 insertions(+), 16 deletions(-) diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index 89b5d7df6..fc194bc59 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') return; let value = filter[key]; let chip; @@ -195,9 +199,10 @@ export default class Searchbar extends Component { doSearch(filter, source) { if (filter === this.filter && source != 'state') return; - let promise = this.onSearch({$params: filter}); + let promise = this.onSearch({$params: filter}, source); promise = promise || this.$q.resolve(); promise.then(data => this.onFilter(filter, source, data)); + this.toBar(filter); } onFilter(filter, source, data) { @@ -247,8 +252,15 @@ 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') this.transition = this.$state.go(state, params, opts).transition; if (source != 'bar' && (source != 'state' || this.$state.is(this.baseState))) @@ -270,6 +282,12 @@ export default class Searchbar extends Component { 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; @@ -283,9 +301,65 @@ export default class Searchbar extends Component { params = this.fetchParams({$params: params}); } - return this.model.applyFilter(where ? {where} : null, params) + if (this.$params.q) + Object.assign(params, JSON.parse(this.$params.q)); + + return this.model.addFilter(where ? {where} : null, params) .then(() => this.model.data); } + + filterSanitizer(field) { + const userFilter = this.model.userFilter; + const userParams = this.model.userParams; + const where = userFilter && userFilter.where; + delete this.$params.q[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/smart-table/index.html b/front/core/components/smart-table/index.html index f26a6b4a2..3168d7ee7 100644 --- a/front/core/components/smart-table/index.html +++ b/front/core/components/smart-table/index.html @@ -103,3 +103,7 @@ + + diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index 9e6e7009c..7880f257f 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -15,9 +15,15 @@ export default class SmartTable extends Component { this.$inputsScope; this.columns = []; this.autoSave = false; + this.autoState = true; this.transclude(); } + $onInit() { + if (this.model) + this.defaultFilter(); + } + $onDestroy() { const styleElement = document.querySelector('style[id="smart-table"]'); if (this.$.css && styleElement) @@ -49,6 +55,7 @@ export default class SmartTable extends Component { this._model = value; if (value) { this.$.model = value; + this.defaultFilter(); this.defaultOrder(); } } @@ -160,6 +167,26 @@ export default class SmartTable extends Component { } } + defaultFilter() { + if (!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 (!order) return; @@ -394,29 +421,56 @@ export default class SmartTable extends Component { this.searchByColumn(field); } - searchByColumn(field) { - const searchCriteria = this.$inputsScope.searchProps[field]; - const emptySearch = searchCriteria === '' || searchCriteria == null; + 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); + } + + searchByColumn(field) { 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]); } addFilter(field, value) { - let where = {[field]: value}; + if (value == '') value = null; - if (this.exprBuilder) { - where = buildFilter(where, (param, value) => - this.exprBuilder({param, value}) - ); + let filterState; + if (this.$params.q) { + filterState = JSON.parse(this.$params.q); + delete filterState.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(); + + if (filterState.tableQ) + Object.assign(searchProps, filterState.tableQ); + + Object.assign(filterState.tableQ, searchProps); + + const params = {q: JSON.stringify(filterState)}; + + this.$state.go(this.$state.current.name, params, {location: 'replace'}); + this.model.refresh(); } applySort() { @@ -517,6 +571,10 @@ export default class SmartTable extends Component { this.model.refresh() .then(() => this.isRefreshing = false); } + + test() { + console.log('USER_FILTER', this.model.userFilter, 'USER_PARAMS', this.model.userParams); + } } SmartTable.$inject = ['$element', '$scope', '$transclude']; From 4df99a82e1a9f7cce8602fd07bbef9cdb99c6d4f Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 28 Sep 2022 11:22:29 +0200 Subject: [PATCH 2/6] feat(tableOrder): save order in url --- e2e/paths/04-item/01_summary.spec.js | 2 +- front/core/components/searchbar/searchbar.js | 15 ++++---- front/core/components/smart-table/index.js | 36 +++++++++++++++----- 3 files changed, 37 insertions(+), 16 deletions(-) diff --git a/e2e/paths/04-item/01_summary.spec.js b/e2e/paths/04-item/01_summary.spec.js index e24fa6a9f..373ceb95a 100644 --- a/e2e/paths/04-item/01_summary.spec.js +++ b/e2e/paths/04-item/01_summary.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -describe('Item summary path', () => { +fdescribe('Item summary path', () => { let browser; let page; beforeAll(async() => { diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index fc194bc59..50f9d0050 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -167,7 +167,7 @@ export default class Searchbar extends Component { let keys = Object.keys(filter); keys.forEach(key => { - if (key == 'search' || key == 'tableQ') return; + if (key == 'search' || key == 'tableQ' || key == 'tableOrder') return; let value = filter[key]; let chip; @@ -281,7 +281,6 @@ export default class Searchbar extends Component { this.model.clear(); return; } - if (Object.keys(filter).length === 0) { this.filterSanitizer('search'); if (this.model.userParams) @@ -301,10 +300,12 @@ export default class Searchbar extends Component { params = this.fetchParams({$params: params}); } - if (this.$params.q) + if (this.$params.q) { Object.assign(params, JSON.parse(this.$params.q)); - - return this.model.addFilter(where ? {where} : null, params) + return this.model.addFilter(where ? {where} : null, params) + .then(() => this.model.data); + } + return this.model.applyFilter(where ? {where} : null, params) .then(() => this.model.data); } @@ -312,7 +313,9 @@ export default class Searchbar extends Component { const userFilter = this.model.userFilter; const userParams = this.model.userParams; const where = userFilter && userFilter.where; - delete this.$params.q[field]; + + if (this.$params.q) + delete this.$params.q[field]; if (this.exprBuilder) { const param = this.exprBuilder({ diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index 7880f257f..c78cbbca0 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -188,7 +188,12 @@ export default class SmartTable extends Component { } defaultOrder() { - const order = this.model.order; + 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(', '); @@ -222,6 +227,9 @@ export default class SmartTable extends Component { this.setPriority(column.element, priority); } } + + this.model.order = order; + this.model.refresh(); } registerColumns() { @@ -443,10 +451,12 @@ export default class SmartTable extends Component { addFilter(field, value) { if (value == '') value = null; - let filterState; + let stateFilter = {tableQ: {}}; if (this.$params.q) { - filterState = JSON.parse(this.$params.q); - delete filterState.tableQ[field]; + stateFilter = JSON.parse(this.$params.q); + if (!stateFilter.tableQ) + stateFilter.tableQ = {}; + delete stateFilter.tableQ[field]; } const whereParams = {[field]: value}; @@ -462,12 +472,9 @@ export default class SmartTable extends Component { const searchProps = this.searchPropsSanitizer(); - if (filterState.tableQ) - Object.assign(searchProps, filterState.tableQ); + Object.assign(stateFilter.tableQ, searchProps); - Object.assign(filterState.tableQ, searchProps); - - const params = {q: JSON.stringify(filterState)}; + const params = {q: JSON.stringify(stateFilter)}; this.$state.go(this.$state.current.name, params, {location: 'replace'}); this.model.refresh(); @@ -480,6 +487,17 @@ export default class SmartTable extends Component { if (order) this.model.order = order; + 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.model.refresh(); } From 84003ab09cff510def09ab0100ada39433a9af28 Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 29 Sep 2022 12:36:16 +0200 Subject: [PATCH 3/6] fix(searchbar): smart-table.tableQ integration --- e2e/helpers/selectors.js | 11 ++- ..._smartTable_searchBar_integrations.spec.js | 77 +++++++++++++++++++ e2e/paths/04-item/01_summary.spec.js | 2 +- .../core/components/crud-model/crud-model.js | 12 +++ front/core/components/searchbar/searchbar.js | 59 ++++++++++++-- .../components/searchbar/searchbar.spec.js | 7 +- 6 files changed, 156 insertions(+), 12 deletions(-) create mode 100644 e2e/paths/01-salix/03_smartTable_searchBar_integrations.spec.js diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 0ad9ad7f4..c8e0ae168 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -392,10 +392,16 @@ export default { 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"]', - saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button' + saveFieldsButton: '.vn-popover.shown vn-button[label="Save"] > button', + 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]', }, 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"]', @@ -405,7 +411,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/e2e/paths/04-item/01_summary.spec.js b/e2e/paths/04-item/01_summary.spec.js index 373ceb95a..e24fa6a9f 100644 --- a/e2e/paths/04-item/01_summary.spec.js +++ b/e2e/paths/04-item/01_summary.spec.js @@ -1,7 +1,7 @@ import selectors from '../../helpers/selectors.js'; import getBrowser from '../../helpers/puppeteer'; -fdescribe('Item summary path', () => { +describe('Item summary path', () => { let browser; let page; beforeAll(async() => { 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 50f9d0050..6e74a3779 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -199,7 +199,7 @@ export default class Searchbar extends Component { doSearch(filter, source) { if (filter === this.filter && source != 'state') return; - let promise = this.onSearch({$params: filter}, source); + let promise = this.onSearch({$params: filter}); promise = promise || this.$q.resolve(); promise.then(data => this.onFilter(filter, source, data)); this.toBar(filter); @@ -243,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'}; } @@ -253,6 +256,7 @@ export default class Searchbar extends Component { this.filter = filter; if (source == 'removeBar') { + console.log(params); delete params[this.toRemove]; delete this.model.userParams[this.toRemove]; this.model.refresh(); @@ -260,7 +264,6 @@ export default class Searchbar extends Component { if (!filter && this.model) this.model.clear(); - if (source != 'state') this.transition = this.$state.go(state, params, opts).transition; if (source != 'bar' && (source != 'state' || this.$state.is(this.baseState))) @@ -296,26 +299,66 @@ export default class Searchbar extends Component { } else { params = Object.assign({}, filter); + console.log('pre', params); if (this.fetchParams) params = this.fetchParams({$params: params}); + console.log('post', params); } - if (this.$params.q) { - Object.assign(params, JSON.parse(this.$params.q)); - return this.model.addFilter(where ? {where} : null, params) + /* console.log(params); + const paramsKeys = Object.keys(params); + const suggestedKeys = Object.keys(this.suggestedFilter); + if (params != this.suggestedFilter) { + for (let suggested in this.suggestedFilter) + delete this.model.userParams[suggested]; + }*/ + console.log('this.fromBar()', this.fromBar()); + console.log('this.$params.q', this.$params.q); + console.log('param', params); + console.log('userParams', this.model.userParams); + console.log('userFilter', this.model.userFilter); + console.log('suggestedFilter', this.suggestedFilter); + console.log('fetch-params', this.fetchParams); + /* if (this.fromBar()) { + for (let param in params) + delete this.model.userParams[param]; + }*/ + this.tableQ = null; + if (this.$params.q && Object.keys(JSON.parse(this.$params.q)).length) { + 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); + console.log('PRE FINAL PARAMS: ', params); + return this.model.applyParams(params) .then(() => this.model.data); } + console.log('FINAL PARAMS: ', params); + 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.$params.q) - delete this.$params.q[field]; + if (this.model.userParams) + delete this.model.userParams[field]; if (this.exprBuilder) { const param = this.exprBuilder({ diff --git a/front/core/components/searchbar/searchbar.spec.js b/front/core/components/searchbar/searchbar.spec.js index e4f58d294..efa98818d 100644 --- a/front/core/components/searchbar/searchbar.spec.js +++ b/front/core/components/searchbar/searchbar.spec.js @@ -172,13 +172,18 @@ describe('Component vnSearchbar', () => { describe('removeParam()', () => { it(`should remove the parameter from the filter`, () => { jest.spyOn(controller, 'doSearch'); + controller.model = { + applyParams: () => { + return new Promise(resolve => resolve()); + } + }; controller.filter = filter; controller.removeParam(0); expect(controller.doSearch).toHaveBeenCalledWith({ search: 'needle' - }, 'bar'); + }, 'removeBar'); }); }); From 94c143bc4ceca4b82f46284971eac172f1f6966d Mon Sep 17 00:00:00 2001 From: alexm Date: Thu, 29 Sep 2022 14:28:50 +0200 Subject: [PATCH 4/6] test(searchbar_smart-table): fix for integration --- front/core/components/searchbar/searchbar.js | 23 --- .../components/searchbar/searchbar.spec.js | 26 +-- front/core/components/smart-table/index.html | 5 +- front/core/components/smart-table/index.js | 26 ++- .../core/components/smart-table/index.spec.js | 159 ++++++++++++------ 5 files changed, 131 insertions(+), 108 deletions(-) diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index 6e74a3779..57a77d980 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -256,7 +256,6 @@ export default class Searchbar extends Component { this.filter = filter; if (source == 'removeBar') { - console.log(params); delete params[this.toRemove]; delete this.model.userParams[this.toRemove]; this.model.refresh(); @@ -299,30 +298,10 @@ export default class Searchbar extends Component { } else { params = Object.assign({}, filter); - console.log('pre', params); if (this.fetchParams) params = this.fetchParams({$params: params}); - console.log('post', params); } - /* console.log(params); - const paramsKeys = Object.keys(params); - const suggestedKeys = Object.keys(this.suggestedFilter); - if (params != this.suggestedFilter) { - for (let suggested in this.suggestedFilter) - delete this.model.userParams[suggested]; - }*/ - console.log('this.fromBar()', this.fromBar()); - console.log('this.$params.q', this.$params.q); - console.log('param', params); - console.log('userParams', this.model.userParams); - console.log('userFilter', this.model.userFilter); - console.log('suggestedFilter', this.suggestedFilter); - console.log('fetch-params', this.fetchParams); - /* if (this.fromBar()) { - for (let param in params) - delete this.model.userParams[param]; - }*/ this.tableQ = null; if (this.$params.q && Object.keys(JSON.parse(this.$params.q)).length) { const stateFilter = JSON.parse(this.$params.q); @@ -341,11 +320,9 @@ export default class Searchbar extends Component { params[param] = stateFilter.tableQ[param]; Object.assign(stateFilter, params); - console.log('PRE FINAL PARAMS: ', params); return this.model.applyParams(params) .then(() => this.model.data); } - console.log('FINAL PARAMS: ', params); return this.model.applyFilter(where ? {where} : null, params) .then(() => this.model.data); diff --git a/front/core/components/searchbar/searchbar.spec.js b/front/core/components/searchbar/searchbar.spec.js index efa98818d..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'); @@ -173,11 +173,15 @@ describe('Component vnSearchbar', () => { it(`should remove the parameter from the filter`, () => { jest.spyOn(controller, 'doSearch'); controller.model = { - applyParams: () => { - return new Promise(resolve => resolve()); + 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); @@ -204,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); @@ -219,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); @@ -234,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); @@ -252,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 3168d7ee7..752019313 100644 --- a/front/core/components/smart-table/index.html +++ b/front/core/components/smart-table/index.html @@ -103,7 +103,4 @@ - - + diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index c78cbbca0..31541143c 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -229,7 +229,7 @@ export default class SmartTable extends Component { } this.model.order = order; - this.model.refresh(); + this.refresh(); } registerColumns() { @@ -429,6 +429,14 @@ export default class SmartTable extends Component { this.searchByColumn(field); } + searchByColumn(field) { + const filters = this.filterSanitizer(field); + + if (filters && filters.userFilter) + this.model.userFilter = filters.userFilter; + this.addFilter(field, this.$inputsScope.searchProps[field]); + } + searchPropsSanitizer() { if (!this.$inputsScope || !this.$inputsScope.searchProps) return null; let searchProps = this.$inputsScope.searchProps; @@ -440,14 +448,6 @@ export default class SmartTable extends Component { return Object.fromEntries(searchProps); } - searchByColumn(field) { - const filters = this.filterSanitizer(field); - - if (filters && filters.userFilter) - this.model.userFilter = filters.userFilter; - this.addFilter(field, this.$inputsScope.searchProps[field]); - } - addFilter(field, value) { if (value == '') value = null; @@ -477,7 +477,7 @@ export default class SmartTable extends Component { const params = {q: JSON.stringify(stateFilter)}; this.$state.go(this.$state.current.name, params, {location: 'replace'}); - this.model.refresh(); + this.refresh(); } applySort() { @@ -498,7 +498,7 @@ export default class SmartTable extends Component { const params = {q: JSON.stringify(stateFilter)}; this.$state.go(this.$state.current.name, params, {location: 'replace'}); - this.model.refresh(); + this.refresh(); } filterSanitizer(field) { @@ -589,10 +589,6 @@ export default class SmartTable extends Component { this.model.refresh() .then(() => this.isRefreshing = false); } - - test() { - console.log('USER_FILTER', this.model.userFilter, 'USER_PARAMS', this.model.userParams); - } } SmartTable.$inject = ['$element', '$scope', '$transclude']; diff --git a/front/core/components/smart-table/index.spec.js b/front/core/components/smart-table/index.spec.js index 720e24c7e..5fd4c33b7 100644 --- a/front/core/components/smart-table/index.spec.js +++ b/front/core/components/smart-table/index.spec.js @@ -9,6 +9,11 @@ describe('Component smartTable', () => { $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); + }); + }); }); From 248572feb438836e32d3b971ea83be1f1b19e03a Mon Sep 17 00:00:00 2001 From: alexm Date: Fri, 14 Oct 2022 07:40:11 +0200 Subject: [PATCH 5/6] use variable --- front/core/components/searchbar/searchbar.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index 57a77d980..dff4836db 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -303,7 +303,9 @@ export default class Searchbar extends Component { } this.tableQ = null; - if (this.$params.q && Object.keys(JSON.parse(this.$params.q)).length) { + + 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') From 9891f7060d6d924015e18cf0034e0936daa577c6 Mon Sep 17 00:00:00 2001 From: alexm Date: Wed, 2 Nov 2022 09:40:09 +0100 Subject: [PATCH 6/6] fix(smart-table): monitor only ticketFilter use url and add ?q in routes --- front/core/components/searchbar/searchbar.js | 2 +- front/core/components/smart-table/index.js | 20 +++++++++++-------- modules/claim/front/routes.json | 6 +++--- modules/client/front/routes.json | 14 ++++++------- modules/item/front/fixed-price/index.html | 14 ++++++------- modules/item/front/fixed-price/index.js | 12 ++--------- .../monitor/front/index/clients/index.html | 16 ++++++++------- modules/route/front/routes.json | 8 ++++---- 8 files changed, 45 insertions(+), 47 deletions(-) diff --git a/front/core/components/searchbar/searchbar.js b/front/core/components/searchbar/searchbar.js index dff4836db..10ec1f608 100644 --- a/front/core/components/searchbar/searchbar.js +++ b/front/core/components/searchbar/searchbar.js @@ -290,7 +290,7 @@ export default class Searchbar extends Component { } let where = null; - let params = null; + let params = {}; if (this.exprBuilder) { where = buildFilter(filter, diff --git a/front/core/components/smart-table/index.js b/front/core/components/smart-table/index.js index 31541143c..8d2c3c153 100644 --- a/front/core/components/smart-table/index.js +++ b/front/core/components/smart-table/index.js @@ -19,9 +19,11 @@ export default class SmartTable extends Component { this.transclude(); } - $onInit() { - if (this.model) + $onChanges() { + if (this.model) { this.defaultFilter(); + this.defaultOrder(); + } } $onDestroy() { @@ -53,11 +55,8 @@ export default class SmartTable extends Component { set model(value) { this._model = value; - if (value) { + if (value) this.$.model = value; - this.defaultFilter(); - this.defaultOrder(); - } } getDefaultViewConfig() { @@ -168,7 +167,8 @@ export default class SmartTable extends Component { } defaultFilter() { - if (!this.$params.q) return; + if (this.disabledTableFilter || !this.$params.q) return; + const stateFilter = JSON.parse(this.$params.q).tableQ; if (!stateFilter || !this.exprBuilder) return; @@ -188,6 +188,8 @@ export default class SmartTable extends Component { } defaultOrder() { + if (this.disabledTableOrder) return; + let stateOrder; if (this.$params.q) stateOrder = JSON.parse(this.$params.q).tableOrder; @@ -607,6 +609,8 @@ ngModule.vnComponent('smartTable', { autoSave: '
- @@ -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 +}