diff --git a/e2e/helpers/selectors.js b/e2e/helpers/selectors.js index 8bda47afe2..4cde8771dd 100644 --- a/e2e/helpers/selectors.js +++ b/e2e/helpers/selectors.js @@ -255,13 +255,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]' }, diff --git a/front/core/components/button/index.js b/front/core/components/button/index.js index 17710967a0..96d68c23b1 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 9a260a690c..ef5c346b9b 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,25 @@ 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 created = res.data; + + // 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]; + } + } + this.applyChanges(); super.save(); }); 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 0000000000..e0daa25588 --- /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 c6f535b7ab..d65ca71df0 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 + } }); }, @@ -66,21 +70,26 @@ module.exports = function(Self) { 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; 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 created; } catch (error) { await tx.rollback(); throw error; diff --git a/modules/item/front/tags/index.html b/modules/item/front/tags/index.html index b7b61107d9..834d4c9774 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> - - +