Merge branch '2076-item_tags_refactor' of verdnatura/salix into dev
gitea/salix/dev This commit looks good
Details
gitea/salix/dev This commit looks good
Details
This commit is contained in:
commit
652e0e6071
|
@ -255,13 +255,13 @@ export default {
|
||||||
fourthRemoveTagButton: 'vn-item-tags vn-horizontal:nth-child(4) vn-icon-button[icon="delete"]',
|
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"]',
|
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"]',
|
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"]',
|
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"]',
|
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"]',
|
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"]',
|
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"]',
|
addItemTagButton: 'vn-item-tags vn-icon-button[icon="add_circle"]',
|
||||||
submitItemTagsButton: 'vn-item-tags button[type=submit]'
|
submitItemTagsButton: 'vn-item-tags button[type=submit]'
|
||||||
},
|
},
|
||||||
|
|
|
@ -9,6 +9,7 @@ export default class Button extends FormInput {
|
||||||
this.initTabIndex();
|
this.initTabIndex();
|
||||||
this.element.addEventListener('keyup', e => this.onKeyup(e));
|
this.element.addEventListener('keyup', e => this.onKeyup(e));
|
||||||
this.element.addEventListener('click', e => this.onClick(e));
|
this.element.addEventListener('click', e => this.onClick(e));
|
||||||
|
this.button = this.element.querySelector('button');
|
||||||
}
|
}
|
||||||
|
|
||||||
$onInit() {
|
$onInit() {
|
||||||
|
@ -21,6 +22,8 @@ export default class Button extends FormInput {
|
||||||
switch (event.key) {
|
switch (event.key) {
|
||||||
case ' ':
|
case ' ':
|
||||||
case 'Enter':
|
case 'Enter':
|
||||||
|
if (this.button)
|
||||||
|
return this.button.click();
|
||||||
return this.element.click();
|
return this.element.click();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -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)
|
if (!this.isChanged)
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
let deletes = [];
|
let deletes = [];
|
||||||
let updates = [];
|
let updates = [];
|
||||||
let creates = [];
|
let creates = [];
|
||||||
|
let orgDeletes = [];
|
||||||
|
let orgUpdates = [];
|
||||||
|
let orgCreates = [];
|
||||||
|
|
||||||
let pk = this.primaryKey;
|
let pk = this.primaryKey;
|
||||||
|
|
||||||
for (let row of this.removed)
|
for (let row of this.removed) {
|
||||||
deletes.push(row.$orgRow[pk]);
|
deletes.push(row.$orgRow[pk]);
|
||||||
|
orgDeletes.push(row);
|
||||||
|
}
|
||||||
|
|
||||||
for (let row of this._data) {
|
for (let row of this.data) {
|
||||||
if (row.$isNew) {
|
if (row.$isNew) {
|
||||||
let data = {};
|
let data = {};
|
||||||
for (let prop in row) {
|
for (let prop in row) {
|
||||||
if (prop.charAt(0) !== '$')
|
if (prop.charAt(0) !== '$')
|
||||||
data[prop] = row[prop];
|
data[prop] = row[prop];
|
||||||
}
|
}
|
||||||
creates.push(data);
|
creates.push(row);
|
||||||
|
orgCreates.push(row);
|
||||||
} else if (row.$oldData) {
|
} else if (row.$oldData) {
|
||||||
let data = {};
|
let data = {};
|
||||||
for (let prop in row.$oldData)
|
for (let prop in row.$oldData)
|
||||||
|
@ -161,6 +167,7 @@ export default class CrudModel extends ModelProxy {
|
||||||
data,
|
data,
|
||||||
where: {[pk]: row.$orgRow[pk]}
|
where: {[pk]: row.$orgRow[pk]}
|
||||||
});
|
});
|
||||||
|
orgUpdates.push(row);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -171,23 +178,25 @@ export default class CrudModel extends ModelProxy {
|
||||||
changes[prop] = undefined;
|
changes[prop] = undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
return changes;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Saves current changes on the server.
|
|
||||||
*
|
|
||||||
* @return {Promise} The save request promise
|
|
||||||
*/
|
|
||||||
save() {
|
|
||||||
let changes = this.getChanges();
|
|
||||||
|
|
||||||
if (!changes)
|
if (!changes)
|
||||||
return this.$q.resolve();
|
return this.$q.resolve();
|
||||||
|
|
||||||
let url = this.saveUrl ? this.saveUrl : `${this._url}/crud`;
|
let url = this.saveUrl ? this.saveUrl : `${this._url}/crud`;
|
||||||
return this.$http.post(url, changes)
|
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();
|
this.applyChanges();
|
||||||
super.save();
|
super.save();
|
||||||
});
|
});
|
||||||
|
|
|
@ -0,0 +1,50 @@
|
||||||
|
describe('Component vnCrudModel', () => {
|
||||||
|
let $httpBackend;
|
||||||
|
let controller;
|
||||||
|
let $element;
|
||||||
|
|
||||||
|
beforeEach(ngModule('vnCore'));
|
||||||
|
|
||||||
|
beforeEach(inject(($compile, $rootScope, _$httpBackend_) => {
|
||||||
|
$element = $compile(`<vn-crud-model></vn-crud-model>`)($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();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
|
@ -50,7 +50,11 @@ module.exports = function(Self) {
|
||||||
description: `Instances to create`,
|
description: `Instances to create`,
|
||||||
type: ['Object']
|
type: ['Object']
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
returns: {
|
||||||
|
type: ['object'],
|
||||||
|
root: true
|
||||||
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
|
||||||
|
@ -66,21 +70,26 @@ module.exports = function(Self) {
|
||||||
promises.push(this.destroyById(id, options));
|
promises.push(this.destroyById(id, options));
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (updates) {
|
if (updates) {
|
||||||
let promises = [];
|
let promises = [];
|
||||||
for (let update of updates)
|
for (let update of updates)
|
||||||
promises.push(this.upsertWithWhere(update.where, update.data, options));
|
promises.push(this.upsertWithWhere(update.where, update.data, options));
|
||||||
await Promise.all(promises);
|
await Promise.all(promises);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let created;
|
||||||
if (creates && creates.length) {
|
if (creates && creates.length) {
|
||||||
try {
|
try {
|
||||||
await this.create(creates, options);
|
created = await this.create(creates, options);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
throw error[error.length - 1];
|
throw error[error.length - 1];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
await tx.commit();
|
await tx.commit();
|
||||||
|
|
||||||
|
return created;
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
await tx.rollback();
|
await tx.rollback();
|
||||||
throw error;
|
throw error;
|
||||||
|
|
|
@ -22,16 +22,14 @@
|
||||||
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
<form name="form" ng-submit="$ctrl.onSubmit()" class="vn-w-md">
|
||||||
<vn-card class="vn-pa-lg">
|
<vn-card class="vn-pa-lg">
|
||||||
<vn-horizontal ng-repeat="itemTag in $ctrl.itemTags">
|
<vn-horizontal ng-repeat="itemTag in $ctrl.itemTags">
|
||||||
<vn-autocomplete
|
<vn-autocomplete vn-one vn-id="tag" vn-focus
|
||||||
vn-one
|
|
||||||
vn-id="tag"
|
|
||||||
label="Tag"
|
label="Tag"
|
||||||
initial-data="itemTag.tag"
|
initial-data="itemTag.tag"
|
||||||
ng-model="itemTag.tagFk"
|
ng-model="itemTag.tagFk"
|
||||||
data="tags"
|
data="tags"
|
||||||
on-change="$ctrl.getSourceTable(tag)"
|
on-change="$ctrl.getSourceTable(tag)"
|
||||||
show-field="name"
|
show-field="name"
|
||||||
vn-focus>
|
rule>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield
|
<vn-textfield
|
||||||
ng-show="tag.selection.isFree || tag.selection.isFree == undefined"
|
ng-show="tag.selection.isFree || tag.selection.isFree == undefined"
|
||||||
|
@ -41,24 +39,22 @@
|
||||||
ng-model="itemTag.value"
|
ng-model="itemTag.value"
|
||||||
rule>
|
rule>
|
||||||
</vn-textfield>
|
</vn-textfield>
|
||||||
<vn-autocomplete
|
<vn-autocomplete vn-three
|
||||||
ng-show="tag.selection.isFree === false"
|
ng-show="tag.selection.isFree === false"
|
||||||
vn-three
|
|
||||||
url="{{$ctrl.sourceTables[itemTag.id].url}}"
|
url="{{$ctrl.sourceTables[itemTag.id].url}}"
|
||||||
search-function="{name: {like: '%'+ $search +'%'}}"
|
search-function="{name: {like: '%'+ $search +'%'}}"
|
||||||
label="Value"
|
label="Value"
|
||||||
ng-model="itemTag.value"
|
ng-model="itemTag.value"
|
||||||
show-field="{{$ctrl.sourceTables[itemTag.id].field}}"
|
show-field="{{$ctrl.sourceTables[itemTag.id].field}}"
|
||||||
value-field="{{$ctrl.sourceTables[itemTag.id].field}}">
|
value-field="{{$ctrl.sourceTables[itemTag.id].field}}"
|
||||||
|
rule>
|
||||||
</vn-autocomplete>
|
</vn-autocomplete>
|
||||||
<vn-textfield
|
<vn-input-number vn-one
|
||||||
tab-index="-1"
|
|
||||||
vn-one
|
|
||||||
type="number"
|
type="number"
|
||||||
label="Relevancy"
|
label="Relevancy"
|
||||||
ng-model="itemTag.priority"
|
ng-model="itemTag.priority"
|
||||||
rule>
|
rule>
|
||||||
</vn-textfield>
|
</vn-input-number>
|
||||||
<vn-none>
|
<vn-none>
|
||||||
<vn-icon-button
|
<vn-icon-button
|
||||||
vn-tooltip="Remove tag"
|
vn-tooltip="Remove tag"
|
||||||
|
|
Loading…
Reference in New Issue