diff --git a/application/Espo/Resources/i18n/en_US/Global.json b/application/Espo/Resources/i18n/en_US/Global.json
index 2c62a535f2..f31478555a 100644
--- a/application/Espo/Resources/i18n/en_US/Global.json
+++ b/application/Espo/Resources/i18n/en_US/Global.json
@@ -522,7 +522,10 @@
"isEmpty": "Is Empty",
"isNotEmpty": "Is Not Empty",
"isOneOf": "Is One Of",
- "isFromTeams": "Is From Team"
+ "isFromTeams": "Is From Team",
+ "isNot": "Is Not",
+ "isNotOneOf": "Is Not One Of",
+ "anyOf": "Any Of"
},
"varcharSearchRanges": {
"equals": "Equals",
diff --git a/client/res/templates/fields/link-multiple/search.tpl b/client/res/templates/fields/link-multiple/search.tpl
index 70241e6214..b380b68e7d 100644
--- a/client/res/templates/fields/link-multiple/search.tpl
+++ b/client/res/templates/fields/link-multiple/search.tpl
@@ -1,3 +1,7 @@
+
+
diff --git a/client/res/templates/fields/link/search.tpl b/client/res/templates/fields/link/search.tpl
index ff03df7e0b..44231d7953 100644
--- a/client/res/templates/fields/link/search.tpl
+++ b/client/res/templates/fields/link/search.tpl
@@ -9,7 +9,7 @@
-
+
diff --git a/client/src/views/fields/link-multiple.js b/client/src/views/fields/link-multiple.js
index 88a7479203..ee8767268a 100644
--- a/client/src/views/fields/link-multiple.js
+++ b/client/src/views/fields/link-multiple.js
@@ -58,6 +58,8 @@ Espo.define('views/fields/link-multiple', 'views/fields/base', function (Dep) {
sortable: false,
+ searchTypeList: ['anyOf'],
+
data: function () {
var ids = this.model.get(this.idsName);
@@ -145,6 +147,10 @@ Espo.define('views/fields/link-multiple', 'views/fields/base', function (Dep) {
}
},
+ setupSearch: function () {
+ this.searchParams.typeFront = this.searchParams.typeFront || 'anyOf';
+ },
+
getAutocompleteUrl: function () {
var url = this.foreignScope + '?sortBy=name&maxCount=' + this.AUTOCOMPLETE_RESULT_MAX_COUNT;
var boolList = this.getSelectBoolFilterList();
@@ -311,15 +317,22 @@ Espo.define('views/fields/link-multiple', 'views/fields/base', function (Dep) {
},
fetchSearch: function () {
- var values = this.ids || [];
+ var type = this.$el.find('select.search-type').val();
- var data = {
- type: 'linkedWith',
- value: values,
- nameHash: this.nameHash
- };
- return data;
- },
+ if (type === 'anyOf') {
+ var values = this.ids || [];
+
+ var data = {
+ type: 'linkedWith',
+ value: this.ids || [],
+ nameHash: this.nameHash,
+ data: {
+ typeFront: type
+ }
+ };
+ return data;
+ }
+ }
});
});
diff --git a/client/src/views/fields/link.js b/client/src/views/fields/link.js
index 403c7d6429..c1b16ae216 100644
--- a/client/src/views/fields/link.js
+++ b/client/src/views/fields/link.js
@@ -54,7 +54,7 @@ Espo.define('views/fields/link', 'views/fields/base', function (Dep) {
createDisabled: false,
- searchTypeList: ['is', 'isEmpty', 'isNotEmpty', 'isOneOf'],
+ searchTypeList: ['is', 'isEmpty', 'isNotEmpty', 'isNot', 'isOneOf', 'isNotOneOf'],
data: function () {
return _.extend({
@@ -167,6 +167,7 @@ Espo.define('views/fields/link', 'views/fields/base', function (Dep) {
setupSearch: function () {
this.searchData.oneOfIdList = this.searchParams.oneOfIdList || [];
this.searchData.oneOfNameHash = this.searchParams.oneOfNameHash || {};
+ this.searchData.idValue = this.searchParams.idValue || this.searchParams.value;
this.events = _.extend({
'change select.search-type': function (e) {
@@ -177,13 +178,13 @@ Espo.define('views/fields/link', 'views/fields/base', function (Dep) {
},
handleSearchType: function (type) {
- if (~['is'].indexOf(type)) {
+ if (~['is', 'isNot', 'isNotAndIsNotEmpty'].indexOf(type)) {
this.$el.find('div.primary').removeClass('hidden');
} else {
this.$el.find('div.primary').addClass('hidden');
}
- if (type === 'isOneOf') {
+ if (~['isOneOf', 'isNotOneOf', 'isNotOneOfAndIsNotEmpty'].indexOf(type)) {
this.$el.find('div.one-of-container').removeClass('hidden');
} else {
this.$el.find('div.one-of-container').addClass('hidden');
@@ -329,7 +330,7 @@ Espo.define('views/fields/link', 'views/fields/base', function (Dep) {
var type = this.$el.find('select.search-type').val();
this.handleSearchType(type);
- if (type == 'isOneOf') {
+ if (~['isOneOf', 'isNotOneOf', 'isNotOneOfAndIsNotEmpty'].indexOf(type)) {
this.searchData.oneOfIdList.forEach(function (id) {
this.addLinkOneOfHtml(id, this.searchData.oneOfNameHash[id]);
}, this);
@@ -425,7 +426,79 @@ Espo.define('views/fields/link', 'views/fields/base', function (Dep) {
}
};
return data;
-
+ } else if (type == 'isNotOneOf') {
+ var data = {
+ type: 'or',
+ value: [
+ {
+ type: 'notIn',
+ attribute: this.searchData.oneOfIdList,
+ value: value
+ },
+ {
+ type: 'isNull',
+ attribute: this.idName
+ }
+ ],
+ field: this.idName,
+ oneOfIdList: this.searchData.oneOfIdList,
+ oneOfNameHash: this.searchData.oneOfNameHash,
+ data: {
+ type: type
+ }
+ };
+ return data;
+ } else if (type == 'isNotOneOfAndIsNotEmpty') {
+ var data = {
+ type: 'notIn',
+ field: this.idName,
+ value: this.searchData.oneOfIdList,
+ oneOfIdList: this.searchData.oneOfIdList,
+ oneOfNameHash: this.searchData.oneOfNameHash,
+ data: {
+ type: type
+ }
+ };
+ return data;
+ } else if (type == 'isNot') {
+ if (!value) {
+ return false;
+ }
+ var data = {
+ type: 'or',
+ value: [
+ {
+ type: 'notEquals',
+ attribute: this.idName,
+ value: value
+ },
+ {
+ type: 'isNull',
+ attribute: this.idName
+ }
+ ],
+ field: this.idName,
+ idValue: value,
+ valueName: this.$el.find('[name="' + this.nameName + '"]').val(),
+ data: {
+ type: type
+ }
+ };
+ return data;
+ } else if (type == 'isNotAndIsNotEmpty') {
+ if (!value) {
+ return false;
+ }
+ var data = {
+ type: 'notEquals',
+ field: this.idName,
+ value: value,
+ valueName: this.$el.find('[name="' + this.nameName + '"]').val(),
+ data: {
+ type: type
+ }
+ };
+ return data;
} else {
if (!value) {
return false;