From e3b1a4b58aad9e834b90237edf4eff2444db2f9e Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 6 Feb 2020 07:41:51 +0100 Subject: [PATCH 1/4] 2076 - Item tags refactor --- front/core/components/button/index.js | 3 + .../core/components/crud-model/crud-model.js | 56 +++++++++++++------ loopback/common/models/vn-model.js | 19 +++++-- modules/item/front/tags/index.html | 18 +++--- 4 files changed, 63 insertions(+), 33 deletions(-) diff --git a/front/core/components/button/index.js b/front/core/components/button/index.js index 17710967a..96d68c23b 100644 --- a/front/core/components/button/index.js +++ b/front/core/components/button/index.js @@ -9,6 +9,7 @@ export default class Button extends FormInput { this.initTabIndex(); this.element.addEventListener('keyup', e => this.onKeyup(e)); this.element.addEventListener('click', e => this.onClick(e)); + this.button = this.element.querySelector('button'); } $onInit() { @@ -21,6 +22,8 @@ export default class Button extends FormInput { switch (event.key) { case ' ': case 'Enter': + if (this.button) + return this.button.click(); return this.element.click(); } } diff --git a/front/core/components/crud-model/crud-model.js b/front/core/components/crud-model/crud-model.js index 9a260a690..563444ddf 100644 --- a/front/core/components/crud-model/crud-model.js +++ b/front/core/components/crud-model/crud-model.js @@ -128,31 +128,37 @@ export default class CrudModel extends ModelProxy { } /** - * Returns an object with the unsaved changes made to the model. + * Saves current changes on the server. * - * @return {Object} The current changes + * @return {Promise} The save request promise */ - getChanges() { + save() { if (!this.isChanged) return null; let deletes = []; let updates = []; let creates = []; + let orgDeletes = []; + let orgUpdates = []; + let orgCreates = []; let pk = this.primaryKey; - for (let row of this.removed) + for (let row of this.removed) { deletes.push(row.$orgRow[pk]); + orgDeletes.push(row); + } - for (let row of this._data) { + for (let row of this.data) { if (row.$isNew) { let data = {}; for (let prop in row) { if (prop.charAt(0) !== '$') data[prop] = row[prop]; } - creates.push(data); + creates.push(row); + orgCreates.push(row); } else if (row.$oldData) { let data = {}; for (let prop in row.$oldData) @@ -161,6 +167,7 @@ export default class CrudModel extends ModelProxy { data, where: {[pk]: row.$orgRow[pk]} }); + orgUpdates.push(row); } } @@ -171,23 +178,36 @@ export default class CrudModel extends ModelProxy { changes[prop] = undefined; } - return changes; - } - - /** - * Saves current changes on the server. - * - * @return {Promise} The save request promise - */ - save() { - let changes = this.getChanges(); - if (!changes) return this.$q.resolve(); let url = this.saveUrl ? this.saveUrl : `${this._url}/crud`; return this.$http.post(url, changes) - .then(() => { + .then(res => { + const newData = res.data; + const created = newData.created; + const updated = newData.updated; + + // Apply new data to created instances + for (let i = 0; i < orgCreates.length; i++) { + const row = orgCreates[i]; + row[pk] = created[i][pk]; + + for (let prop in row) { + if (prop.charAt(0) !== '$') + row[prop] = created[i][prop]; + } + } + + // Apply new data to updated instances + for (let i = 0; i < orgUpdates.length; i++) { + const row = orgUpdates[i]; + for (let prop in row) { + if (prop.charAt(0) !== '$') + row[prop] = updated[i][prop]; + } + } + this.applyChanges(); super.save(); }); diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js index c6f535b7a..d535606e0 100644 --- a/loopback/common/models/vn-model.js +++ b/loopback/common/models/vn-model.js @@ -50,7 +50,11 @@ module.exports = function(Self) { description: `Instances to create`, type: ['Object'] } - ] + ], + returns: { + type: ['object'], + root: true + } }); }, @@ -60,27 +64,34 @@ module.exports = function(Self) { try { let options = {transaction: tx}; + let deleted; if (deletes) { let promises = []; for (let id of deletes) promises.push(this.destroyById(id, options)); - await Promise.all(promises); + deleted = await Promise.all(promises); } + + let updated; if (updates) { let promises = []; for (let update of updates) promises.push(this.upsertWithWhere(update.where, update.data, options)); - await Promise.all(promises); + updated = await Promise.all(promises); } + + let created; if (creates && creates.length) { try { - await this.create(creates, options); + created = await this.create(creates, options); } catch (error) { throw error[error.length - 1]; } } await tx.commit(); + + return {deleted, created, updated}; } catch (error) { await tx.rollback(); throw error; diff --git a/modules/item/front/tags/index.html b/modules/item/front/tags/index.html index b7b61107d..834d4c977 100644 --- a/modules/item/front/tags/index.html +++ b/modules/item/front/tags/index.html @@ -22,16 +22,14 @@
- + rule> - + value-field="{{$ctrl.sourceTables[itemTag.id].field}}" + rule> - - + Date: Thu, 6 Feb 2020 10:31:39 +0100 Subject: [PATCH 2/4] updated selector --- e2e/helpers/selectors.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 0399f7b17..003d5830e 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -253,13 +253,13 @@ export default { fourthRemoveTagButton: 'vn-item-tags vn-horizontal:nth-child(4) vn-icon-button[icon="delete"]', fifthTag: 'vn-item-tags vn-horizontal:nth-child(5) > vn-autocomplete[ng-model="itemTag.tagFk"]', fifthValue: 'vn-item-tags vn-horizontal:nth-child(5) vn-textfield[ng-model="itemTag.value"]', - fifthRelevancy: 'vn-item-tags vn-horizontal:nth-child(5) vn-textfield[ng-model="itemTag.priority"]', + fifthRelevancy: 'vn-item-tags vn-horizontal:nth-child(5) vn-input-number[ng-model="itemTag.priority"]', sixthTag: 'vn-item-tags vn-horizontal:nth-child(6) > vn-autocomplete[ng-model="itemTag.tagFk"]', sixthValue: 'vn-item-tags vn-horizontal:nth-child(6) vn-textfield[ng-model="itemTag.value"]', - sixthRelevancy: 'vn-item-tags vn-horizontal:nth-child(6) vn-textfield[ng-model="itemTag.priority"]', + sixthRelevancy: 'vn-item-tags vn-horizontal:nth-child(6) vn-input-number[ng-model="itemTag.priority"]', seventhTag: 'vn-item-tags vn-horizontal:nth-child(7) > vn-autocomplete[ng-model="itemTag.tagFk"]', seventhValue: 'vn-item-tags vn-horizontal:nth-child(7) vn-textfield[ng-model="itemTag.value"]', - seventhRelevancy: 'vn-item-tags vn-horizontal:nth-child(7) vn-textfield[ng-model="itemTag.priority"]', + seventhRelevancy: 'vn-item-tags vn-horizontal:nth-child(7) vn-input-number[ng-model="itemTag.priority"]', addItemTagButton: 'vn-item-tags vn-icon-button[icon="add_circle"]', submitItemTagsButton: 'vn-item-tags button[type=submit]' }, From b77f32a733cac20ed3d1a55e01108c414edf3b4f Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 6 Feb 2020 10:43:46 +0100 Subject: [PATCH 3/4] requested changes --- front/core/components/crud-model/crud-model.js | 13 +------------ loopback/common/models/vn-model.js | 6 +----- 2 files changed, 2 insertions(+), 17 deletions(-) diff --git a/front/core/components/crud-model/crud-model.js b/front/core/components/crud-model/crud-model.js index 563444ddf..ef5c346b9 100644 --- a/front/core/components/crud-model/crud-model.js +++ b/front/core/components/crud-model/crud-model.js @@ -184,9 +184,7 @@ export default class CrudModel extends ModelProxy { let url = this.saveUrl ? this.saveUrl : `${this._url}/crud`; return this.$http.post(url, changes) .then(res => { - const newData = res.data; - const created = newData.created; - const updated = newData.updated; + const created = res.data; // Apply new data to created instances for (let i = 0; i < orgCreates.length; i++) { @@ -199,15 +197,6 @@ export default class CrudModel extends ModelProxy { } } - // Apply new data to updated instances - for (let i = 0; i < orgUpdates.length; i++) { - const row = orgUpdates[i]; - for (let prop in row) { - if (prop.charAt(0) !== '$') - row[prop] = updated[i][prop]; - } - } - this.applyChanges(); super.save(); }); diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js index d535606e0..592392666 100644 --- a/loopback/common/models/vn-model.js +++ b/loopback/common/models/vn-model.js @@ -64,20 +64,16 @@ module.exports = function(Self) { try { let options = {transaction: tx}; - let deleted; if (deletes) { let promises = []; for (let id of deletes) promises.push(this.destroyById(id, options)); - deleted = await Promise.all(promises); } - let updated; if (updates) { let promises = []; for (let update of updates) promises.push(this.upsertWithWhere(update.where, update.data, options)); - updated = await Promise.all(promises); } let created; @@ -91,7 +87,7 @@ module.exports = function(Self) { await tx.commit(); - return {deleted, created, updated}; + return created; } catch (error) { await tx.rollback(); throw error; From c7c79831d51d97fc5977dca558244802b969ec8b Mon Sep 17 00:00:00 2001 From: Joan Sanchez Date: Thu, 6 Feb 2020 13:38:46 +0100 Subject: [PATCH 4/4] added crud-model save() unit test --- .../core/components/crud-model/index.spec.js | 50 +++++++++++++++++++ loopback/common/models/vn-model.js | 2 + 2 files changed, 52 insertions(+) create mode 100644 front/core/components/crud-model/index.spec.js diff --git a/front/core/components/crud-model/index.spec.js b/front/core/components/crud-model/index.spec.js new file mode 100644 index 000000000..e0daa2558 --- /dev/null +++ b/front/core/components/crud-model/index.spec.js @@ -0,0 +1,50 @@ +describe('Component vnCrudModel', () => { + let $httpBackend; + let controller; + let $element; + + beforeEach(ngModule('vnCore')); + + beforeEach(inject(($compile, $rootScope, _$httpBackend_) => { + $element = $compile(``)($rootScope); + $httpBackend = _$httpBackend_; + controller = $element.controller('vnCrudModel'); + controller.orgData = [ + {id: 1, value: 'My item 1'}, + {id: 2, value: 'My item 2'} + ]; + controller.data = [ + {id: 1, value: 'My item 1'}, + {id: 2, value: 'My item 2'} + ]; + controller._url = 'Model'; + })); + + afterEach(() => { + $element.remove(); + }); + + describe('save()', () => { + it(`should make an HTTP post query and then update the original rows with the returned values`, () => { + spyOn(controller, 'applyChanges'); + + controller.insert({value: 'My new item 1'}); + controller.insert({value: 'My new item 2'}); + + $httpBackend.when('POST', 'Model/crud').respond([ + {id: 3, value: 'My new item 1'}, + {id: 4, value: 'My modified item 2'} + ]); + controller.save(); + $httpBackend.flush(); + + const thirdRow = controller.data[2]; + const fourthRow = controller.data[3]; + + expect(thirdRow.id).toEqual(3); + expect(fourthRow.id).toEqual(4); + expect(fourthRow.value).toEqual('My modified item 2'); + expect(controller.applyChanges).toHaveBeenCalledWith(); + }); + }); +}); diff --git a/loopback/common/models/vn-model.js b/loopback/common/models/vn-model.js index 592392666..d65ca71df 100644 --- a/loopback/common/models/vn-model.js +++ b/loopback/common/models/vn-model.js @@ -68,12 +68,14 @@ module.exports = function(Self) { let promises = []; for (let id of deletes) promises.push(this.destroyById(id, options)); + await Promise.all(promises); } if (updates) { let promises = []; for (let update of updates) promises.push(this.upsertWithWhere(update.where, update.data, options)); + await Promise.all(promises); } let created;