diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Task.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Task.json
index 420e4ccedd..d14f377489 100644
--- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Task.json
+++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Task.json
@@ -17,6 +17,21 @@
"type": "equals",
"attribute": "status",
"value": "Completed"
+ },
+ {
+ "type": "or",
+ "value": [
+ {
+ "type": "notEquals",
+ "attribute": "status",
+ "value": "Not Started"
+ },
+ {
+ "type": "notEquals",
+ "attribute": "status",
+ "value": "Canceled"
+ }
+ ]
}
]
}
diff --git a/application/Espo/Resources/i18n/en_US/Admin.json b/application/Espo/Resources/i18n/en_US/Admin.json
index d1fb44a674..2dbff2df22 100644
--- a/application/Espo/Resources/i18n/en_US/Admin.json
+++ b/application/Espo/Resources/i18n/en_US/Admin.json
@@ -138,7 +138,10 @@
"prefix": "Prefix",
"nextNumber": "Next Number",
"padLength": "Pad Length",
- "disableFormatting": "Disable Formatting"
+ "disableFormatting": "Disable Formatting",
+ "dynamicLogicVisible": "Conditions making field visible",
+ "dynamicLogicReadOnly": "Conditions making field read-only",
+ "dynamicLogicRequired": "Conditions making field required"
},
"messages": {
"upgradeVersion": "Your EspoCRM will be upgraded to version {version}. This can take some time.",
@@ -190,5 +193,10 @@
"medium": "Medium",
"large": "Large"
}
+ },
+ "logicalOperators": {
+ "and": "AND",
+ "or": "OR",
+ "not": "NOT"
}
}
diff --git a/application/Espo/Resources/i18n/en_US/FieldManager.json b/application/Espo/Resources/i18n/en_US/FieldManager.json
new file mode 100644
index 0000000000..a4e4de5032
--- /dev/null
+++ b/application/Espo/Resources/i18n/en_US/FieldManager.json
@@ -0,0 +1,5 @@
+{
+ "labels": {
+ "Dynamic Logic": "Dynamic Logic"
+ }
+}
diff --git a/client/res/templates/admin/dynamic-logic/conditions-string/group-base.tpl b/client/res/templates/admin/dynamic-logic/conditions-string/group-base.tpl
new file mode 100644
index 0000000000..03e73e00b6
--- /dev/null
+++ b/client/res/templates/admin/dynamic-logic/conditions-string/group-base.tpl
@@ -0,0 +1,14 @@
+{{#if isEmpty}}
+ {{translate 'None'}}
+{{else}}
+
(
+ {{#each viewDataList}}
+
{{{var key ../this}}}
+ {{#unless isEnd}}
+
+ {{translate ../../operator category='logicalOperators' scope='Admin'}}
+
+ {{/unless}}
+ {{/each}}
+ )
+{{/if}}
\ No newline at end of file
diff --git a/client/res/templates/admin/dynamic-logic/conditions-string/item-base.tpl b/client/res/templates/admin/dynamic-logic/conditions-string/item-base.tpl
new file mode 100644
index 0000000000..fedaa7ee78
--- /dev/null
+++ b/client/res/templates/admin/dynamic-logic/conditions-string/item-base.tpl
@@ -0,0 +1 @@
+{{translate field category='fields' scope=scope}} {{{operatorString}}} {{{value}}}
\ No newline at end of file
diff --git a/client/res/templates/admin/field-manager/edit.tpl b/client/res/templates/admin/field-manager/edit.tpl
index e1e10d7acc..cba73c85f0 100644
--- a/client/res/templates/admin/field-manager/edit.tpl
+++ b/client/res/templates/admin/field-manager/edit.tpl
@@ -32,5 +32,16 @@
+
+
{{translate 'Dynamic Logic' scope='FieldManager'}}
+
+ {{#if dynamicLogicVisible}}
+
+ {{/if}}
+
+
diff --git a/client/res/templates/admin/field-manager/fields/dynamic-logic-conditions/edit.tpl b/client/res/templates/admin/field-manager/fields/dynamic-logic-conditions/edit.tpl
new file mode 100644
index 0000000000..2173968c5f
--- /dev/null
+++ b/client/res/templates/admin/field-manager/fields/dynamic-logic-conditions/edit.tpl
@@ -0,0 +1,9 @@
+
+
+
+
+ {{{conditionGroup}}}
+
+
diff --git a/client/src/views/admin/dynamic-logic/conditions-string/and.js b/client/src/views/admin/dynamic-logic/conditions-string/and.js
new file mode 100644
index 0000000000..f6cc3f8d78
--- /dev/null
+++ b/client/src/views/admin/dynamic-logic/conditions-string/and.js
@@ -0,0 +1,38 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
+ ************************************************************************/
+
+Espo.define('views/admin/dynamic-logic/conditions-string/and', 'views/admin/dynamic-logic/conditions-string/group-base', function (Dep) {
+
+ return Dep.extend({
+
+ operator: 'and'
+
+ });
+
+});
+
diff --git a/client/src/views/admin/dynamic-logic/conditions-string/equals.js b/client/src/views/admin/dynamic-logic/conditions-string/equals.js
new file mode 100644
index 0000000000..9bea556fea
--- /dev/null
+++ b/client/src/views/admin/dynamic-logic/conditions-string/equals.js
@@ -0,0 +1,38 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
+ ************************************************************************/
+
+Espo.define('views/admin/dynamic-logic/conditions-string/equals', 'views/admin/dynamic-logic/conditions-string/item-base', function (Dep) {
+
+ return Dep.extend({
+
+ operatorString: '='
+
+ });
+
+});
+
diff --git a/client/src/views/admin/dynamic-logic/conditions-string/group-base.js b/client/src/views/admin/dynamic-logic/conditions-string/group-base.js
new file mode 100644
index 0000000000..b8489bd22f
--- /dev/null
+++ b/client/src/views/admin/dynamic-logic/conditions-string/group-base.js
@@ -0,0 +1,86 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
+ ************************************************************************/
+
+Espo.define('views/admin/dynamic-logic/conditions-string/group-base', 'view', function (Dep) {
+
+ return Dep.extend({
+
+ template: 'admin/dynamic-logic/conditions-string/group-base',
+
+ data: function () {
+ var isEmpty = false;
+ if (!this.conditionList.length) {
+ return {
+ isEmpty: true
+ };
+ }
+ return {
+ viewDataList: this.viewDataList,
+ operator: this.operator
+ };
+ },
+
+ setup: function () {
+ this.level = this.options.level || 0;
+ this.number = this.options.number || 0;
+ this.scope = this.options.scope;
+
+ this.itemData = this.options.itemData || {};
+ this.viewList = [];
+
+ var conditionList = this.conditionList = this.itemData.value || [];
+
+ this.viewDataList = [];
+ conditionList.forEach(function (item, i) {
+ var key = 'view-' + this.level.toString() + '-' + this.number.toString() + '-' + i.toString();
+
+ this.createItemView(i, key, item);
+ this.viewDataList.push({
+ key: key,
+ isEnd: i === conditionList.length - 1
+ });
+ }, this);
+ },
+
+ createItemView: function (number, key, item) {
+ this.viewList.push(key);
+
+ var type = item.type || 'equals';
+ this.createView(key, 'views/admin/dynamic-logic/conditions-string/' + Espo.Utils.camelCaseToHyphen(type), {
+ itemData: item,
+ scope: this.scope,
+ level: this.level + 1,
+ el: '[data-view-key="'+key+'"]',
+ number: number
+ });
+ },
+
+ });
+
+});
+
diff --git a/client/src/views/admin/dynamic-logic/conditions-string/item-base.js b/client/src/views/admin/dynamic-logic/conditions-string/item-base.js
new file mode 100644
index 0000000000..04c724b80d
--- /dev/null
+++ b/client/src/views/admin/dynamic-logic/conditions-string/item-base.js
@@ -0,0 +1,90 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
+ ************************************************************************/
+
+Espo.define('views/admin/dynamic-logic/conditions-string/item-base', 'view', function (Dep) {
+
+ return Dep.extend({
+
+ template: 'admin/dynamic-logic/conditions-string/item-base',
+
+ data: function () {
+ return {
+ valueViewKey: this.getValueViewKey(),
+ scope: this.scope,
+ operator: this.operator,
+ operatorString: this.operatorString,
+ field: this.field
+ };
+ },
+
+ setup: function () {
+ this.itemData = this.options.itemData;
+
+ this.level = this.options.level || 0;
+ this.number = this.options.number || 0;
+ this.scope = this.options.scope;
+
+ this.field = (this.itemData.data || {}).field || this.itemData.attribute;
+
+ this.additionalData = (this.itemData.data || {});
+
+ this.wait(true);
+
+ this.getModelFactory().create(this.scope, function (model) {
+ this.model = model;
+
+ model.set(this.itemData.attribute, this.itemData.value);
+ model.set(this.additionalData.values || {})
+
+ this.createValueFieldView();
+
+ this.wait(false);
+ }, this);
+ },
+
+ getValueViewKey: function () {
+ return 'view-' + this.level.toString() + '-' + this.number.toString() + '-0';
+ },
+
+ createValueFieldView: function () {
+ var key = this.getValueViewKey();
+
+ var fieldType = this.getMetadata().get(['entityDefs', this.scope, this.field, 'type']) || 'base';
+ var viewName = this.getMetadata().get(['entityDefs', this.scope, this.field, 'view']) || this.getFieldManager().getViewName(fieldType);
+
+ this.createView('value', viewName, {
+ model: this.model,
+ name: this.field,
+ el: '[data-view-key="'+key+'"]'
+ });
+ },
+
+ });
+
+});
+
diff --git a/client/src/views/admin/dynamic-logic/conditions-string/not-equals.js b/client/src/views/admin/dynamic-logic/conditions-string/not-equals.js
new file mode 100644
index 0000000000..fc85bf8ecc
--- /dev/null
+++ b/client/src/views/admin/dynamic-logic/conditions-string/not-equals.js
@@ -0,0 +1,38 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
+ ************************************************************************/
+
+Espo.define('views/admin/dynamic-logic/conditions-string/not-equals', 'views/admin/dynamic-logic/conditions-string/item-base', function (Dep) {
+
+ return Dep.extend({
+
+ operatorString: '≠'
+
+ });
+
+});
+
diff --git a/client/src/views/admin/dynamic-logic/conditions-string/or.js b/client/src/views/admin/dynamic-logic/conditions-string/or.js
new file mode 100644
index 0000000000..71bcebbf65
--- /dev/null
+++ b/client/src/views/admin/dynamic-logic/conditions-string/or.js
@@ -0,0 +1,38 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
+ ************************************************************************/
+
+Espo.define('views/admin/dynamic-logic/conditions-string/or', 'views/admin/dynamic-logic/conditions-string/group-base', function (Dep) {
+
+ return Dep.extend({
+
+ operator: 'or'
+
+ });
+
+});
+
diff --git a/client/src/views/admin/field-manager/edit.js b/client/src/views/admin/field-manager/edit.js
index 84ace59fde..ccccfbf868 100644
--- a/client/src/views/admin/field-manager/edit.js
+++ b/client/src/views/admin/field-manager/edit.js
@@ -147,6 +147,14 @@ Espo.define('views/admin/field-manager/edit', ['view', 'model'], function (Dep,
this.createFieldView(o.type, o.name, null, o);
}, this);
+ if (!this.getMetadata().get(['entityDefs', this.scope, this.field, 'layoutDetailDisabled'])) {
+ this.model.set('dynamicLogicVisible', this.getMetadata().get(['clientDefs', this.scope, 'dynamicLogic', 'fields', this.field, 'visible']));
+ this.createFieldView(null, 'dynamicLogicVisible', null, {
+ view: 'views/admin/field-manager/fields/dynamic-logic-conditions',
+ scope: this.scope
+ });
+ }
+
callback();
}.bind(this));
diff --git a/client/src/views/admin/field-manager/fields/dynamic-logic-conditions.js b/client/src/views/admin/field-manager/fields/dynamic-logic-conditions.js
new file mode 100644
index 0000000000..0ff26032ad
--- /dev/null
+++ b/client/src/views/admin/field-manager/fields/dynamic-logic-conditions.js
@@ -0,0 +1,152 @@
+/************************************************************************
+ * This file is part of EspoCRM.
+ *
+ * EspoCRM - Open Source CRM application.
+ * Copyright (C) 2014-2015 Yuri Kuznetsov, Taras Machyshyn, Oleksiy Avramenko
+ * Website: http://www.espocrm.com
+ *
+ * EspoCRM is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * EspoCRM is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with EspoCRM. If not, see http://www.gnu.org/licenses/.
+ *
+ * The interactive user interfaces in modified source and object code versions
+ * of this program must display Appropriate Legal Notices, as required under
+ * Section 5 of the GNU General Public License version 3.
+ *
+ * In accordance with Section 7(b) of the GNU General Public License version 3,
+ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
+ ************************************************************************/
+
+Espo.define('views/admin/field-manager/fields/dynamic-logic-conditions', 'views/fields/base', function (Dep) {
+
+ return Dep.extend({
+
+ editTemplate: 'admin/field-manager/fields/dynamic-logic-conditions/edit',
+
+ data: function () {
+ },
+
+ setup: function () {
+ var conditionGroup = (this.model.get(this.name) || {}).conditionGroup || [];
+
+ this.createView('conditionGroup', 'views/admin/dynamic-logic/conditions-string/and', {
+ itemData: {
+ type: 'and',
+ value: conditionGroup
+ },
+ scope: this.options.scope
+ });
+ },
+
+ getConditionsString: function () {
+ var data = (this.model.get(this.name) || {}).conditionGroup || [];
+ if (!data.length) {
+ return this.translate('None');
+ }
+ return this.stringifyConditionGroup(data);
+ },
+
+ stringifyConditionGroup: function (group, type) {
+ type = type || 'and';
+ if (type === 'and' || type === 'or') {
+ var list = [];
+ (group || []).forEach(function (item) {
+ list.push(this.stringifyConditionItem(item));
+ }, this);
+ return list.join(' ' + this.translate('and', 'logicalOperators', 'Admin') + ' ');
+ } else if (type === 'not') {
+ return this.translate('not', 'logicalOperators', 'Admin') + ' (' + this.stringifyConditionItem(group) + ')';
+ }
+ },
+
+ stringifyConditionItem: function (item) {
+ if (!item) return '';
+ item = item || {};
+ var type = item.type || 'equals';
+ var value = item.value || null;
+
+ if (~['and', 'or', 'not'].indexOf(type)) {
+ return '(' + this.stringifyConditionGroup(value, type) + ')';
+ }
+
+ var operator;
+ switch (type) {
+ case 'equals':
+ operator = '=';
+ break;
+ case 'notEquals':
+ operator = '≠';
+ break;
+ case 'greaterThan':
+ operator = '>';
+ break;
+ case 'lessThan':
+ operator = '<';
+ break;
+ case 'greaterThanOrEquals':
+ operator = '≥';
+ break;
+ case 'greaterThanOrEquals':
+ operator = '≤';
+ break;
+ case 'isEmpty':
+ operator = '= ∅';
+ break;
+ case 'isNotEmpty':
+ operator = '≠ ∅';
+ break;
+ case 'in':
+ operator = '∈';
+ case 'notIn':
+ operator = '∉';
+ break;
+ default:
+ return '';
+ }
+
+ if (!item.attribute) return;
+
+ var attribute = item.attribute;
+
+ var part = attribute;
+
+ switch (type) {
+ case 'in':
+ case 'notIn':
+ part = part + ' ' + operator + ' (' + (value || []).map(function (valueItem) {
+ return this.stringifyValue(valueItem, item);
+ }, this).join(', ') + ')';
+ break;
+ case 'isEmpty':
+ case 'isNotEmpty':
+ part = part + ' ' + operator;
+ break;
+ default:
+ part = part + ' ' + operator + ' ' + this.stringifyValue(value, item);
+ }
+
+ return part;
+ },
+
+ stringifyValue: function (value, item) {
+ var field = (item.data || {}).field || item.attribute;
+
+ var fieldType = this.getMetadata().get(['entityDefs', this.options.scope, 'fields', field]);
+
+ this.getLanguage().translateOption(item, item.attribute, this.options.scope);
+
+
+ return value;
+ },
+ });
+
+});