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}} +
+ +
{{{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 @@ + +
+
+ {{translate 'Edit'}} +
+
+ {{{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; + }, + }); + +});