diff --git a/client/item/src/locale/es.yml b/client/item/src/locale/es.yml
index abf9d1859..07191a246 100644
--- a/client/item/src/locale/es.yml
+++ b/client/item/src/locale/es.yml
@@ -21,4 +21,5 @@ Date: Fecha
Preview: Vista previa
Clone: Clonar
Do you want to clone this item?: ¿Desea clonar este artículo?
-Yes, clone: Si, clonar
\ No newline at end of file
+Yes, clone: Si, clonar
+Value: Valor
\ No newline at end of file
diff --git a/client/item/src/tags/item-tags.html b/client/item/src/tags/item-tags.html
index 8f00b0b29..17369ca48 100644
--- a/client/item/src/tags/item-tags.html
+++ b/client/item/src/tags/item-tags.html
@@ -1,5 +1,43 @@
-
-
- Item tags
-
-
\ No newline at end of file
+
+
+
\ No newline at end of file
diff --git a/client/item/src/tags/item-tags.js b/client/item/src/tags/item-tags.js
index a390820b7..bdbd8cd48 100644
--- a/client/item/src/tags/item-tags.js
+++ b/client/item/src/tags/item-tags.js
@@ -1,5 +1,128 @@
import ngModule from '../module';
+class ItemTags {
+ constructor($http, $scope, $translate, vnApp, params) {
+ this.$http = $http;
+ this.$scope = $scope;
+ this.$translate = $translate;
+ this.vnApp = vnApp;
+ this.itemId = params.id;
+ this.itemTags = [];
+ this.itemTagsRemoved = [];
+ this.oldItemTags = {};
+ }
+
+ _setIconAdd() {
+ if (this.itemTags.length) {
+ this.itemTags.map(element => {
+ element.showAddIcon = false;
+ return true;
+ });
+ this.itemTags[this.itemTags.length - 1].showAddIcon = true;
+ } else {
+ this.addItemTag();
+ }
+ }
+ _setDirtyForm() {
+ if (this.$scope.form) {
+ this.$scope.form.$setDirty();
+ }
+ }
+ _unsetDirtyForm() {
+ if (this.$scope.form) {
+ this.$scope.form.$setPristine();
+ }
+ }
+
+ removeItemTag(index) {
+ let item = this.itemTags[index];
+ if (item) {
+ this.itemTags.splice(index, 1);
+ this._setIconAdd();
+ if (item.id) {
+ this.itemTagsRemoved.push(item.id);
+ this._setDirtyForm();
+ }
+ }
+ }
+
+ addItemTag() {
+ this.itemTags.push({value: null, itemFk: this.item.id, tagFk: null, showAddIcon: true});
+ this._setIconAdd();
+ }
+
+ _setOlTags(itemTags) {
+ itemTags.map(tag => {
+ this.oldItemTags[tag.id] = Object.assign({}, tag);
+ return tag;
+ });
+ this._setIconAdd();
+ }
+
+ _getItemtags() {
+ let filter = {
+ where: {itemFk: this.itemId},
+ order: "priority ASC",
+ include: {relation: "tag"}
+ };
+ this.$http.get(`/item/api/ItemTags?filter=${JSON.stringify(filter)}`).then(response => {
+ this.itemTags = response.data;
+ this._setOlTags(response.data);
+ });
+ }
+
+ _equalItemTags(tagOld, tagNew) {
+ return tagOld.tagFk === tagNew.tagFk && tagOld.value === tagNew.value;
+ }
+
+ submit() {
+ let codes = [];
+ let repeatedItemTags = false;
+ let canSubmit;
+ let submitObj = {
+ delete: this.itemTagsRemoved,
+ create: [],
+ update: []
+ };
+ for (let i = 0; i < this.itemTags.length; i++) {
+ let itemTag = this.itemTags[i];
+ let isNewItemTag = itemTag.id === undefined;
+
+ if (itemTag.tagFk && codes.indexOf(itemTag.tagFk) !== -1) {
+ repeatedItemTags = true;
+ break;
+ }
+ if (itemTag.tagFk) codes.push(itemTag.tagFk);
+
+ if (isNewItemTag && itemTag.tagFk) {
+ submitObj.create.push(itemTag);
+ } else if (!isNewItemTag && !this._equalItemTags(this.oldItemTags[itemTag.id], itemTag)) {
+ submitObj.update.push(itemTag);
+ }
+ }
+
+ if (repeatedItemTags) {
+ return this.vnApp.showMessage(this.$translate.instant('The barcode must be unique'));
+ }
+
+ canSubmit = submitObj.update.length > 0 || submitObj.create.length > 0 || submitObj.delete.length > 0;
+
+ if (canSubmit) {
+ return this.$http.post(`/item/api/ItemTags/crudItemTags`, submitObj).then(() => {
+ this._getItemtags();
+ this._unsetDirtyForm();
+ });
+ }
+ this.vnApp.showMessage(this.$translate.instant('No changes to save'));
+ }
+
+ $onInit() {
+ this._getItemtags();
+ }
+}
+ItemTags.$inject = ['$http', '$scope', '$translate', 'vnApp', '$stateParams'];
+
ngModule.component('vnItemTags', {
- template: require('./item-tags.html')
+ template: require('./item-tags.html'),
+ controller: ItemTags
});
diff --git a/services/item/common/methods/item/crudItemTags.js b/services/item/common/methods/item/crudItemTags.js
new file mode 100644
index 000000000..e02497e58
--- /dev/null
+++ b/services/item/common/methods/item/crudItemTags.js
@@ -0,0 +1,36 @@
+module.exports = Self => {
+ Self.remoteMethod('crudItemTags', {
+ description: 'create, update or delete itemTags',
+ accessType: 'WRITE',
+ accepts: [
+ {
+ arg: 'itemtags',
+ type: 'Object',
+ require: true,
+ description: 'object with itemTags to create, update or delete, Example: {create: [], update: [], delete: []}',
+ http: {source: 'body'}
+ }
+ ],
+ http: {
+ path: `/crudItemTags`,
+ verb: 'post'
+ }
+ });
+
+ Self.crudItemTags = itemtags => {
+ let promises = [];
+
+ if (itemtags.delete && itemtags.delete.length) {
+ promises.push(Self.destroyAll({id: {inq: itemtags.delete}}));
+ }
+ if (itemtags.create.length) {
+ promises.push(Self.create(itemtags.create));
+ }
+ if (itemtags.update.length) {
+ itemtags.update.forEach(itemtag => {
+ promises.push(Self.upsert(itemtag));
+ });
+ }
+ return Promise.all(promises);
+ };
+};
diff --git a/services/item/common/models/item-tag.js b/services/item/common/models/item-tag.js
new file mode 100644
index 000000000..d4e768bdb
--- /dev/null
+++ b/services/item/common/models/item-tag.js
@@ -0,0 +1,3 @@
+module.exports = function(Self) {
+ require('../methods/item/crudItemTags.js')(Self);
+};