diff --git a/.idea/jsonSchemas.xml b/.idea/jsonSchemas.xml index 859c5652b2..20c366d73d 100644 --- a/.idea/jsonSchemas.xml +++ b/.idea/jsonSchemas.xml @@ -1386,6 +1386,25 @@ + + + + + + + diff --git a/.vscode/settings.json b/.vscode/settings.json index 1db639ab7d..6aac458309 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -82,6 +82,12 @@ ], "url": "./schema/metadata/integrations.json" }, + { + "fileMatch": [ + "*/metadata/logicDefs/*.json" + ], + "url": "./schema/metadata/logicDefs.json" + }, { "fileMatch": [ "*/metadata/notificationDefs/*.json" diff --git a/application/Espo/Core/Upgrades/Migrations/V9_1/AfterUpgrade.php b/application/Espo/Core/Upgrades/Migrations/V9_1/AfterUpgrade.php index 3ac76c0cb9..87a661e7ac 100644 --- a/application/Espo/Core/Upgrades/Migrations/V9_1/AfterUpgrade.php +++ b/application/Espo/Core/Upgrades/Migrations/V9_1/AfterUpgrade.php @@ -31,19 +31,24 @@ namespace Espo\Core\Upgrades\Migrations\V9_1; use Espo\Core\ORM\Repository\Option\SaveOption; use Espo\Core\Upgrades\Migration\Script; +use Espo\Core\Utils\Metadata; +use Espo\Core\Utils\ObjectUtil; use Espo\Modules\Crm\Entities\KnowledgeBaseArticle; use Espo\ORM\EntityManager; use Espo\Tools\Email\Util; +use stdClass; class AfterUpgrade implements Script { public function __construct( private EntityManager $entityManager, + private Metadata $metadata, ) {} public function run(): void { $this->processKbArticles(); + $this->processDynamicLogicMetadata(); } private function processKbArticles(): void @@ -71,4 +76,32 @@ class AfterUpgrade implements Script $this->entityManager->saveEntity($article, [SaveOption::SKIP_HOOKS => true]); } } + + private function processDynamicLogicMetadata(): void + { + /** @var string[] $scopes */ + $scopes = array_keys($this->metadata->get('clientDefs', [])); + + foreach ($scopes as $scope) { + $customClientDefs = $this->metadata->getCustom('clientDefs', $scope); + + if (!$customClientDefs instanceof stdClass) { + continue; + } + + if ( + !property_exists($customClientDefs, 'dynamicLogic') || + !$customClientDefs->dynamicLogic instanceof stdClass + ) { + continue; + } + + $this->metadata->saveCustom('logicDefs', $scope, $customClientDefs->dynamicLogic); + + $customClientDefs = ObjectUtil::clone($customClientDefs); + unset($customClientDefs->dynamicLogic); + + $this->metadata->saveCustom('clientDefs', $scope, $customClientDefs); + } + } } diff --git a/application/Espo/Core/Utils/Metadata/AdditionalBuilder/LogicDefsBc.php b/application/Espo/Core/Utils/Metadata/AdditionalBuilder/LogicDefsBc.php new file mode 100644 index 0000000000..ff8d9b0ac9 --- /dev/null +++ b/application/Espo/Core/Utils/Metadata/AdditionalBuilder/LogicDefsBc.php @@ -0,0 +1,162 @@ +. + * + * 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 Affero General Public License version 3. + * + * In accordance with Section 7(b) of the GNU Affero General Public License version 3, + * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. + ************************************************************************/ + +namespace Espo\Core\Utils\Metadata\AdditionalBuilder; + +use Espo\Core\Utils\Metadata\AdditionalBuilder; +use Espo\Core\Utils\ObjectUtil; +use stdClass; + +/** + * Establishes backward compatibility of clientDefs > {scope} > dynamicLogic. + * The dynamic logic is NOT supposed to be set in custom clientDefs as of v9.1. + * The custom dynamic logic is supposed to be moved to logicDefs by an upgrade script. + * But extensions can have a dynamic logic defined in clientDefs as they may be supposed + * to be compatible with older Espo versions. + * + * @noinspection PhpUnused + */ +class LogicDefsBc implements AdditionalBuilder +{ + public function build(stdClass $data): void + { + if (!isset($data->clientDefs)) { + return; + } + + /** @var array $clientDefs */ + $clientDefs = get_object_vars($data->clientDefs); + + foreach ($clientDefs as $scope => $defs) { + $this->processScope($scope, $data); + } + } + + private function processScope(string $scope, stdClass $data): void + { + if (!isset($data->clientDefs->$scope)) { + return; + } + + /** @var stdClass $clientDefs */ + $clientDefs = $data->clientDefs->$scope; + + if (!isset($clientDefs->dynamicLogic)) { + return; + } + + /** @var stdClass $dynamicLogic */ + $dynamicLogic = $clientDefs->dynamicLogic; + + $keys = [ + 'fields', + 'panels', + ]; + + $subKeys = [ + 'visible', + 'required', + 'readOnly', + 'invalid', + ]; + + $data->logicDefs ??= (object) []; + $data->logicDefs->$scope ??= (object) []; + + /** @var stdClass $logicDefs */ + $logicDefs = $data->logicDefs->$scope; + + $customFile = "custom/Espo/Custom/Resources/metadata/logicDefs/$scope.json"; + + $customLogicDefs = file_exists($customFile) ? + json_decode(file_get_contents($customFile) ?: '') : + null; + + if (!$customLogicDefs instanceof stdClass) { + $customLogicDefs = (object) []; + } + + foreach ($keys as $key) { + if (!isset($dynamicLogic->$key)) { + continue; + } + + /** @var array $defs */ + $defs = get_object_vars($dynamicLogic->$key); + + foreach ($defs as $name => $subDefs) { + + foreach ($subKeys as $subKey) { + if (!property_exists($subDefs, $subKey)) { + continue; + } + + if ( + isset($customLogicDefs->$key->$name) && + property_exists($customLogicDefs->$key->$name, $subKey) + ) { + // Overridden in custom. + continue; + } + + /** @var stdClass|null $item */ + $item = $subDefs->$subKey; + + $logicDefs->$key ??= (object) []; + $logicDefs->$key->$name ??= (object) []; + + $logicDefs->$key->$name->$subKey = $item !== null ? + ObjectUtil::clone($item) : + null; + } + } + } + + if (isset($dynamicLogic->options)) { + /** @var array $defs */ + $defs = get_object_vars($dynamicLogic->options); + + foreach ($defs as $name => $subDefs) { + if ( + isset($customLogicDefs->options) && + property_exists($customLogicDefs->options, $name) + ) { + // Overridden in custom. + continue; + } + + $logicDefs->options ??= (object) []; + + $logicDefs->options->$name = $subDefs !== null ? + array_map(fn ($it) => ObjectUtil::clone($it), $subDefs) : + null; + } + } + } +} diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Campaign.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Campaign.json index 6de160245f..074a5c7a4d 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Campaign.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Campaign.json @@ -80,166 +80,6 @@ "filterList": [ "active" ], - "dynamicLogic": { - "fields": { - "targetLists": { - "visible": { - "conditionGroup": [ - { - "type": "or", - "value": [ - { - "type": "equals", - "attribute": "type", - "value": "Email" - }, - { - "type": "equals", - "attribute": "type", - "value": "Newsletter" - }, - { - "type": "equals", - "attribute": "type", - "value": "Informational Email" - }, - { - "type": "equals", - "attribute": "type", - "value": "Mail" - } - ] - } - ] - } - }, - "excludingTargetLists": { - "visible": { - "conditionGroup": [ - { - "type": "or", - "value": [ - { - "type": "equals", - "attribute": "type", - "value": "Email" - }, - { - "type": "equals", - "attribute": "type", - "value": "Newsletter" - }, - { - "type": "equals", - "attribute": "type", - "value": "Informational Email" - }, - { - "type": "equals", - "attribute": "type", - "value": "Mail" - } - ] - } - ] - } - }, - "contactsTemplate": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "type", - "value": "Mail" - } - ] - } - }, - "leadsTemplate": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "type", - "value": "Mail" - } - ] - } - }, - "accountsTemplate": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "type", - "value": "Mail" - } - ] - } - }, - "usersTemplate": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "type", - "value": "Mail" - } - ] - } - }, - "mailMergeOnlyWithAddress": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "type", - "value": "Mail" - } - ] - } - } - }, - "panels": { - "massEmails": { - "visible": { - "conditionGroup": [ - { - "type": "in", - "attribute": "type", - "value": [ - "Email", - "Newsletter", - "Informational Email" - ] - } - ] - } - }, - "trackingUrls": { - "visible": { - "conditionGroup": [ - { - "type": "in", - "attribute": "type", - "value": ["Email", "Newsletter"] - } - ] - } - }, - "mailMerge": { - "visible": { - "conditionGroup": [ - { - "type": "in", - "attribute": "type", - "value": ["Mail"] - } - ] - } - } - } - }, "boolFilterList": ["onlyMy"], "iconClass": "fas fa-chart-line" } diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/CampaignTrackingUrl.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/CampaignTrackingUrl.json index 0be9c76f69..f72ce9f23d 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/CampaignTrackingUrl.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/CampaignTrackingUrl.json @@ -8,49 +8,5 @@ "defaultSidePanel": { "edit": false, "editSmall": false - }, - "dynamicLogic": { - "fields": { - "url": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "action", - "value": "Redirect" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "action", - "value": "Redirect" - } - ] - } - }, - "message": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "action", - "value": "Show Message" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "action", - "value": "Show Message" - } - ] - } - } - } } } diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json index e8292c966b..4ddbb3bc2c 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Case.json @@ -104,20 +104,6 @@ "filter": "open" }, "allowInternalNotes": true, - "dynamicLogic": { - "fields": { - "number": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - } - } - }, "additionalLayouts": { "detailPortal": { "type": "detail" diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json index 8550990671..72f0bdf762 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Contact.json @@ -98,33 +98,6 @@ "filterList": [ "portalUsers" ], - "dynamicLogic": { - "fields": { - "title": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "accountId" - } - ] - } - }, - "portalUser": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "portalUserId", - "data": { - "field": "portalUser" - } - } - ] - } - } - } - }, "color": "#a4c5e0", "iconClass": "fas fa-id-badge" } diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/MassEmail.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/MassEmail.json index c81f729eaa..e9ea244244 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/MassEmail.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/MassEmail.json @@ -28,65 +28,6 @@ ] } }, - "dynamicLogic": { - "fields": { - "status": { - "readOnly": { - "conditionGroup": [ - { - "type": "and", - "value": [ - { - "type": "or", - "value": [ - { - "type": "equals", - "attribute": "status", - "value": "Complete" - }, - { - "type": "equals", - "attribute": "status", - "value": "In Process" - }, - { - "type": "equals", - "attribute": "status", - "value": "Failed" - } - ] - }, - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - ] - } - } - }, - "options": { - "status": [ - { - "optionList": [ - "Draft", - "Pending" - ], - "conditionGroup": [ - { - "type": "in", - "attribute": "status", - "value": [ - "Draft", - "Pending" - ] - } - ] - } - ] - } - }, "filterList": [ { "name":"actual" diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json index 94c3c97e6f..dc8bd23e1c 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Opportunity.json @@ -99,21 +99,6 @@ "selectHandler": "handlers/select-related/same-account-many" } }, - "dynamicLogic": { - "fields": { - "lastStage": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "stage", - "value": "Closed Lost" - } - ] - } - } - } - }, "color": "#9fc77e", "iconClass": "fas fa-dollar-sign" } diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/TargetList.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/TargetList.json index 201da6d7ed..f818da6294 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/TargetList.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/TargetList.json @@ -88,29 +88,5 @@ "massSelect": true } }, - "dynamicLogic": { - "fields": { - "entryCount": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - }, - "optedOutCount": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - } - } - }, "iconClass":"fas fa-crosshairs" } diff --git a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Task.json b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Task.json index e08d486664..86da441f15 100644 --- a/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Task.json +++ b/application/Espo/Modules/Crm/Resources/metadata/clientDefs/Task.json @@ -46,21 +46,6 @@ "checkVisibilityFunction": "isCompleteAvailable" } ], - "dynamicLogic": { - "fields": { - "dateCompleted": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "status", - "value": "Completed" - } - ] - } - } - } - }, "filterList": [ "actual", { diff --git a/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Campaign.json b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Campaign.json new file mode 100644 index 0000000000..acb41d069e --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Campaign.json @@ -0,0 +1,160 @@ +{ + "fields": { + "targetLists": { + "visible": { + "conditionGroup": [ + { + "type": "or", + "value": [ + { + "type": "equals", + "attribute": "type", + "value": "Email" + }, + { + "type": "equals", + "attribute": "type", + "value": "Newsletter" + }, + { + "type": "equals", + "attribute": "type", + "value": "Informational Email" + }, + { + "type": "equals", + "attribute": "type", + "value": "Mail" + } + ] + } + ] + } + }, + "excludingTargetLists": { + "visible": { + "conditionGroup": [ + { + "type": "or", + "value": [ + { + "type": "equals", + "attribute": "type", + "value": "Email" + }, + { + "type": "equals", + "attribute": "type", + "value": "Newsletter" + }, + { + "type": "equals", + "attribute": "type", + "value": "Informational Email" + }, + { + "type": "equals", + "attribute": "type", + "value": "Mail" + } + ] + } + ] + } + }, + "contactsTemplate": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "type", + "value": "Mail" + } + ] + } + }, + "leadsTemplate": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "type", + "value": "Mail" + } + ] + } + }, + "accountsTemplate": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "type", + "value": "Mail" + } + ] + } + }, + "usersTemplate": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "type", + "value": "Mail" + } + ] + } + }, + "mailMergeOnlyWithAddress": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "type", + "value": "Mail" + } + ] + } + } + }, + "panels": { + "massEmails": { + "visible": { + "conditionGroup": [ + { + "type": "in", + "attribute": "type", + "value": [ + "Email", + "Newsletter", + "Informational Email" + ] + } + ] + } + }, + "trackingUrls": { + "visible": { + "conditionGroup": [ + { + "type": "in", + "attribute": "type", + "value": ["Email", "Newsletter"] + } + ] + } + }, + "mailMerge": { + "visible": { + "conditionGroup": [ + { + "type": "in", + "attribute": "type", + "value": ["Mail"] + } + ] + } + } + } +} diff --git a/application/Espo/Modules/Crm/Resources/metadata/logicDefs/CampaignTrackingUrl.json b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/CampaignTrackingUrl.json new file mode 100644 index 0000000000..e5cc25a631 --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/CampaignTrackingUrl.json @@ -0,0 +1,44 @@ +{ + "fields": { + "url": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "action", + "value": "Redirect" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "action", + "value": "Redirect" + } + ] + } + }, + "message": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "action", + "value": "Show Message" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "action", + "value": "Show Message" + } + ] + } + } + } +} diff --git a/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Case.json b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Case.json new file mode 100644 index 0000000000..170d40a9dc --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Case.json @@ -0,0 +1,14 @@ +{ + "fields": { + "number": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + } + } +} diff --git a/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Contact.json b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Contact.json new file mode 100644 index 0000000000..690d2f8be1 --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Contact.json @@ -0,0 +1,27 @@ +{ + "fields": { + "title": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "accountId" + } + ] + } + }, + "portalUser": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "portalUserId", + "data": { + "field": "portalUser" + } + } + ] + } + } + } +} diff --git a/application/Espo/Modules/Crm/Resources/metadata/logicDefs/MassEmail.json b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/MassEmail.json new file mode 100644 index 0000000000..c00fd2979b --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/MassEmail.json @@ -0,0 +1,59 @@ +{ + "fields": { + "status": { + "readOnly": { + "conditionGroup": [ + { + "type": "and", + "value": [ + { + "type": "or", + "value": [ + { + "type": "equals", + "attribute": "status", + "value": "Complete" + }, + { + "type": "equals", + "attribute": "status", + "value": "In Process" + }, + { + "type": "equals", + "attribute": "status", + "value": "Failed" + } + ] + }, + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + ] + } + } + }, + "options": { + "status": [ + { + "optionList": [ + "Draft", + "Pending" + ], + "conditionGroup": [ + { + "type": "in", + "attribute": "status", + "value": [ + "Draft", + "Pending" + ] + } + ] + } + ] + } +} diff --git a/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Opportunity.json b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Opportunity.json new file mode 100644 index 0000000000..55aa8622ef --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Opportunity.json @@ -0,0 +1,15 @@ +{ + "fields": { + "lastStage": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "stage", + "value": "Closed Lost" + } + ] + } + } + } +} diff --git a/application/Espo/Modules/Crm/Resources/metadata/logicDefs/TargetList.json b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/TargetList.json new file mode 100644 index 0000000000..e4ec1b3ece --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/TargetList.json @@ -0,0 +1,24 @@ +{ + "fields": { + "entryCount": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + }, + "optedOutCount": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + } + } +} diff --git a/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Task.json b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Task.json new file mode 100644 index 0000000000..b3f5e720e1 --- /dev/null +++ b/application/Espo/Modules/Crm/Resources/metadata/logicDefs/Task.json @@ -0,0 +1,15 @@ +{ + "fields": { + "dateCompleted": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "status", + "value": "Completed" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/app/metadata.json b/application/Espo/Resources/metadata/app/metadata.json index cbd55a45fe..711292ec86 100644 --- a/application/Espo/Resources/metadata/app/metadata.json +++ b/application/Espo/Resources/metadata/app/metadata.json @@ -51,6 +51,7 @@ "Espo\\Core\\Utils\\Metadata\\AdditionalBuilder\\Fields", "Espo\\Core\\Utils\\Metadata\\AdditionalBuilder\\FilterFields", "Espo\\Core\\Utils\\Metadata\\AdditionalBuilder\\DeleteIdField", - "Espo\\Core\\Utils\\Metadata\\AdditionalBuilder\\StreamUpdatedAtField" + "Espo\\Core\\Utils\\Metadata\\AdditionalBuilder\\StreamUpdatedAtField", + "Espo\\Core\\Utils\\Metadata\\AdditionalBuilder\\LogicDefsBc" ] } diff --git a/application/Espo/Resources/metadata/clientDefs/Email.json b/application/Espo/Resources/metadata/clientDefs/Email.json index 5ad05f7289..4fc78750d4 100644 --- a/application/Espo/Resources/metadata/clientDefs/Email.json +++ b/application/Espo/Resources/metadata/clientDefs/Email.json @@ -123,84 +123,6 @@ "selectHandler": "handlers/email/select-user" } }, - "dynamicLogic":{ - "fields": { - "replied": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "repliedId", - "data": { - "field": "replied" - } - } - ] - } - }, - "replies": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "repliesIds", - "data": { - "field": "replies" - } - } - ] - } - }, - "folderString": { - "visible": { - "conditionGroup": [ - { - "type": "or", - "value": [ - { - "type": "and", - "value": [ - { - "type": "isTrue", - "attribute": "isUsers" - } - ] - }, - { - "type": "isNotEmpty", - "attribute": "groupFolderId" - } - ] - } - - ] - } - }, - "sendAt": { - "visible": { - "conditionGroup": [ - { - "type": "in", - "attribute": "status", - "value": ["Draft"] - } - ] - } - } - }, - "panels": { - "event": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "icsEventDateStart" - } - ] - } - } - } - }, "filterList":[ ], diff --git a/application/Espo/Resources/metadata/clientDefs/EmailAccount.json b/application/Espo/Resources/metadata/clientDefs/EmailAccount.json index 948df4754c..130a32c2f6 100644 --- a/application/Espo/Resources/metadata/clientDefs/EmailAccount.json +++ b/application/Espo/Resources/metadata/clientDefs/EmailAccount.json @@ -35,55 +35,6 @@ ] } }, - "dynamicLogic": { - "fields": { - "smtpUsername": { - "required": { - "conditionGroup": [ - { - "type": "and", - "value": [ - { - "type": "isTrue", - "attribute": "useSmtp" - }, - { - "type": "isTrue", - "attribute": "smtpAuth" - } - ] - } - ] - } - }, - "fetchSince": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "useImap" - } - ] - }, - "readOnly": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "fetchData" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "useImap" - } - ] - } - } - } - }, "filterList": [ { "name": "active" diff --git a/application/Espo/Resources/metadata/clientDefs/EmailFilter.json b/application/Espo/Resources/metadata/clientDefs/EmailFilter.json index d999d66067..8dcf3c661b 100644 --- a/application/Espo/Resources/metadata/clientDefs/EmailFilter.json +++ b/application/Espo/Resources/metadata/clientDefs/EmailFilter.json @@ -23,137 +23,5 @@ }, "boolFilterList": [ "onlyMy" - ], - "dynamicLogic": { - "fields": { - "parent": { - "visible": { - "conditionGroup": [ - { - "attribute": "isGlobal", - "type": "isFalse" - } - ] - }, - "required": { - "conditionGroup": [ - { - "attribute": "isGlobal", - "type": "isFalse" - } - ] - } - }, - "emailFolder": { - "visible": { - "conditionGroup": [ - { - "attribute": "action", - "type": "equals", - "value": "Move to Folder" - } - ] - }, - "required": { - "conditionGroup": [ - { - "attribute": "action", - "type": "equals", - "value": "Move to Folder" - } - ] - } - }, - "groupEmailFolder": { - "visible": { - "conditionGroup": [ - { - "attribute": "action", - "type": "equals", - "value": "Move to Group Folder" - } - ] - }, - "required": { - "conditionGroup": [ - { - "attribute": "action", - "type": "equals", - "value": "Move to Group Folder" - } - ] - } - }, - "markAsRead": { - "visible": { - "conditionGroup": [ - { - "attribute": "parentType", - "type": "equals", - "value": "User" - } - ] - } - }, - "skipNotification": { - "visible": { - "conditionGroup": [ - { - "attribute": "parentType", - "type": "equals", - "value": "User" - } - ] - } - } - }, - "options": { - "action": [ - { - "conditionGroup": [ - { - "attribute": "isGlobal", - "type": "isTrue" - } - ], - "optionList": [ - "Skip" - ] - }, - { - "conditionGroup": [ - { - "attribute": "parentType", - "type": "equals", - "value": "User" - } - ], - "optionList": [ - "Skip", - "Move to Folder", - "None" - ] - }, - { - "conditionGroup": [ - { - "attribute": "parentType", - "type": "equals", - "value": "InboundEmail" - } - ], - "optionList": [ - "Skip", - "Move to Group Folder" - ] - }, - { - "conditionGroup": [], - "optionList": [ - "Skip" - ] - } - ] - } - } + ] } diff --git a/application/Espo/Resources/metadata/clientDefs/InboundEmail.json b/application/Espo/Resources/metadata/clientDefs/InboundEmail.json index 052da3d5ff..5a5a79ce84 100644 --- a/application/Espo/Resources/metadata/clientDefs/InboundEmail.json +++ b/application/Espo/Resources/metadata/clientDefs/InboundEmail.json @@ -29,65 +29,6 @@ ] } }, - "dynamicLogic": { - "fields": { - "smtpUsername": { - "required": { - "conditionGroup": [ - { - "type": "and", - "value": [ - { - "type": "isTrue", - "attribute": "useSmtp" - }, - { - "type": "isTrue", - "attribute": "smtpAuth" - } - ] - } - ] - } - }, - "fetchSince": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "useImap" - } - ] - }, - "readOnly": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "fetchData" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "useImap" - } - ] - } - }, - "isSystem": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - } - } - }, "searchPanelDisabled": true, "relationshipPanels": { "filters": { diff --git a/application/Espo/Resources/metadata/clientDefs/LeadCapture.json b/application/Espo/Resources/metadata/clientDefs/LeadCapture.json index 0422368825..ece82f4efb 100644 --- a/application/Espo/Resources/metadata/clientDefs/LeadCapture.json +++ b/application/Espo/Resources/metadata/clientDefs/LeadCapture.json @@ -5,243 +5,6 @@ "detail": "views/lead-capture/record/detail", "list": "views/lead-capture/record/list" }, - "dynamicLogic": { - "fields": { - "targetList": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "subscribeToTargetList" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "subscribeToTargetList" - } - ] - } - }, - "subscribeContactToTargetList": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "subscribeToTargetList" - } - ] - } - }, - "optInConfirmationLifetime": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "optInConfirmation" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "optInConfirmation" - } - ] - } - }, - "optInConfirmationSuccessMessage": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "optInConfirmation" - } - ] - } - }, - "createLeadBeforeOptInConfirmation": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "optInConfirmation" - } - ] - } - }, - "smtpAccount": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "optInConfirmation" - } - ] - } - }, - "skipOptInConfirmationIfSubscribed": { - "visible": { - "conditionGroup": [ - { - "type": "and", - "value": [ - { - "type": "isTrue", - "attribute": "optInConfirmation" - }, - { - "type": "isNotEmpty", - "attribute": "targetListId", - "data": { - "field": "targetList" - } - } - ] - } - ] - } - }, - "optInConfirmationEmailTemplate": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "optInConfirmation" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "optInConfirmation" - } - ] - } - }, - "apiKey": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - }, - "phoneNumberCountry": { - "visible": { - "conditionGroup": [ - { - "type": "contains", - "attribute": "fieldList", - "value": "phoneNumber" - } - ] - } - }, - "formSuccessText": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - }, - "formTitle": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - }, - "formTheme": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - }, - "formText": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - }, - "formSuccessRedirectUrl": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - }, - "formLanguage": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - }, - "formFrameAncestors": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - }, - "formCaptcha": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - } - }, - "panels": { - "form": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - }, - { - "type": "isTrue", - "attribute": "formEnabled" - } - ] - } - } - } - }, "sidePanels": { "detail": [ { diff --git a/application/Espo/Resources/metadata/clientDefs/OAuthProvider.json b/application/Espo/Resources/metadata/clientDefs/OAuthProvider.json index 035c56421c..4e8be86087 100644 --- a/application/Espo/Resources/metadata/clientDefs/OAuthProvider.json +++ b/application/Espo/Resources/metadata/clientDefs/OAuthProvider.json @@ -6,59 +6,5 @@ "selectDisabled": true, "unlinkDisabled": true } - }, - "dynamicLogic": { - "fields": { - "authorizationRedirectUri": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - }, - "clientId": { - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "isActive" - } - ] - } - }, - "clientSecret": { - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "isActive" - } - ] - } - }, - "authorizationEndpoint": { - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "isActive" - } - ] - } - }, - "tokenEndpoint": { - "required": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "isActive" - } - ] - } - } - } } } diff --git a/application/Espo/Resources/metadata/clientDefs/Preferences.json b/application/Espo/Resources/metadata/clientDefs/Preferences.json index 5bbc002591..dde139f74e 100644 --- a/application/Espo/Resources/metadata/clientDefs/Preferences.json +++ b/application/Espo/Resources/metadata/clientDefs/Preferences.json @@ -6,19 +6,5 @@ "edit": "views/preferences/edit" }, "acl": "acl/preferences", - "aclPortal": "acl-portal/preferences", - "dynamicLogic": { - "fields": { - "assignmentEmailNotificationsIgnoreEntityTypeList": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "receiveAssignmentEmailNotifications" - } - ] - } - } - } - } + "aclPortal": "acl-portal/preferences" } diff --git a/application/Espo/Resources/metadata/clientDefs/Template.json b/application/Espo/Resources/metadata/clientDefs/Template.json index 715f4e8972..3ab2902902 100644 --- a/application/Espo/Resources/metadata/clientDefs/Template.json +++ b/application/Espo/Resources/metadata/clientDefs/Template.json @@ -5,109 +5,5 @@ "edit": "views/template/record/edit" }, "mergeDisabled": true, - "dynamicLogic": { - "fields": { - "entityType": { - "readOnly": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - }, - "footer": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "printFooter" - } - ] - } - }, - "footerPosition": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "printFooter" - } - ] - } - }, - "header": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "printHeader" - } - ] - } - }, - "headerPosition": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "printHeader" - } - ] - } - }, - "body": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "entityType" - } - ] - } - }, - "pageWidth": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "pageFormat", - "value": "Custom" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "pageFormat", - "value": "Custom" - } - ] - } - }, - "pageHeight": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "pageFormat", - "value": "Custom" - } - ] - }, - "required": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "pageFormat", - "value": "Custom" - } - ] - } - } - } - }, "iconClass": "fas fa-file-pdf" } diff --git a/application/Espo/Resources/metadata/clientDefs/User.json b/application/Espo/Resources/metadata/clientDefs/User.json index 8ecbbfe6a5..e3286d0c21 100644 --- a/application/Espo/Resources/metadata/clientDefs/User.json +++ b/application/Espo/Resources/metadata/clientDefs/User.json @@ -122,49 +122,5 @@ "selectRecords": { "orderBy": "userNameOwnFirst" }, - "iconClass": "fas fa-user-circle", - "dynamicLogic": { - "fields": { - "avatarColor": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "avatarId", - "value": null, - "data": { - "field": "avatar" - } - }, - { - "type": "in", - "attribute": "type", - "value": [ - "regular", - "admin", - "api" - ] - } - ] - } - } - }, - "options": { - "authMethod": [ - { - "optionList": [ - "ApiKey", - "Hmac" - ], - "conditionGroup": [ - { - "type": "equals", - "attribute": "type", - "value": "api" - } - ] - } - ] - } - } + "iconClass": "fas fa-user-circle" } diff --git a/application/Espo/Resources/metadata/clientDefs/Webhook.json b/application/Espo/Resources/metadata/clientDefs/Webhook.json index 09840f734d..625b2b8ad2 100644 --- a/application/Espo/Resources/metadata/clientDefs/Webhook.json +++ b/application/Espo/Resources/metadata/clientDefs/Webhook.json @@ -14,29 +14,5 @@ } ] } - }, - "dynamicLogic": { - "fields": { - "event": { - "readOnly": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - }, - "secretKey": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "id" - } - ] - } - } - } } } diff --git a/application/Espo/Resources/metadata/clientDefs/WorkingTimeCalendar.json b/application/Espo/Resources/metadata/clientDefs/WorkingTimeCalendar.json index 30b5edd337..d9eb0151e8 100644 --- a/application/Espo/Resources/metadata/clientDefs/WorkingTimeCalendar.json +++ b/application/Espo/Resources/metadata/clientDefs/WorkingTimeCalendar.json @@ -15,89 +15,5 @@ } ] } - }, - "dynamicLogic": { - "fields": { - "weekday0TimeRanges": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "weekday0" - } - ] - } - }, - "weekday1TimeRanges": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "weekday1" - } - ] - } - }, - "weekday2TimeRanges": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "weekday2" - } - ] - } - }, - "weekday3TimeRanges": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "weekday3" - } - ] - } - }, - "weekday4TimeRanges": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "weekday4" - } - ] - } - }, - "weekday5TimeRanges": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "weekday5" - } - ] - } - }, - "weekday6TimeRanges": { - "visible": { - "conditionGroup": [ - { - "type": "isTrue", - "attribute": "weekday6" - } - ] - } - }, - "teams": { - "visible": { - "conditionGroup": [ - { - "type": "isNotEmpty", - "attribute": "teamsIds" - } - ] - } - } - } } } diff --git a/application/Espo/Resources/metadata/clientDefs/WorkingTimeRange.json b/application/Espo/Resources/metadata/clientDefs/WorkingTimeRange.json index 48a283cb61..a5ed3c670b 100644 --- a/application/Espo/Resources/metadata/clientDefs/WorkingTimeRange.json +++ b/application/Espo/Resources/metadata/clientDefs/WorkingTimeRange.json @@ -16,44 +16,6 @@ ] } }, - "dynamicLogic": { - "fields": { - "timeRanges": { - "visible": { - "conditionGroup": [ - { - "type": "equals", - "attribute": "type", - "value": "Working" - } - ] - } - }, - "users": { - "visible": { - "conditionGroup": [ - { - "type": "or", - "value": [ - { - "type": "isNotEmpty", - "attribute": "id" - }, - { - "type": "isNotEmpty", - "attribute": "usersIds" - }, - { - "type": "isEmpty", - "attribute": "calendarsIds" - } - ] - } - ] - } - } - } - }, "filterList": [ "actual" ] diff --git a/application/Espo/Resources/metadata/logicDefs/Email.json b/application/Espo/Resources/metadata/logicDefs/Email.json new file mode 100644 index 0000000000..910ca23d7b --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/Email.json @@ -0,0 +1,78 @@ +{ + "fields": { + "replied": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "repliedId", + "data": { + "field": "replied" + } + } + ] + } + }, + "replies": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "repliesIds", + "data": { + "field": "replies" + } + } + ] + } + }, + "folderString": { + "visible": { + "conditionGroup": [ + { + "type": "or", + "value": [ + { + "type": "and", + "value": [ + { + "type": "isTrue", + "attribute": "isUsers" + } + ] + }, + { + "type": "isNotEmpty", + "attribute": "groupFolderId" + } + ] + } + + ] + } + }, + "sendAt": { + "visible": { + "conditionGroup": [ + { + "type": "in", + "attribute": "status", + "value": ["Draft"] + } + ] + } + } + }, + "panels": { + "event": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "icsEventDateStart" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/EmailAccount.json b/application/Espo/Resources/metadata/logicDefs/EmailAccount.json new file mode 100644 index 0000000000..d7836314a2 --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/EmailAccount.json @@ -0,0 +1,49 @@ +{ + "fields": { + "smtpUsername": { + "required": { + "conditionGroup": [ + { + "type": "and", + "value": [ + { + "type": "isTrue", + "attribute": "useSmtp" + }, + { + "type": "isTrue", + "attribute": "smtpAuth" + } + ] + } + ] + } + }, + "fetchSince": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "useImap" + } + ] + }, + "readOnly": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "fetchData" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "useImap" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/EmailFilter.json b/application/Espo/Resources/metadata/logicDefs/EmailFilter.json new file mode 100644 index 0000000000..a3ec579283 --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/EmailFilter.json @@ -0,0 +1,132 @@ +{ + "fields": { + "parent": { + "visible": { + "conditionGroup": [ + { + "attribute": "isGlobal", + "type": "isFalse" + } + ] + }, + "required": { + "conditionGroup": [ + { + "attribute": "isGlobal", + "type": "isFalse" + } + ] + } + }, + "emailFolder": { + "visible": { + "conditionGroup": [ + { + "attribute": "action", + "type": "equals", + "value": "Move to Folder" + } + ] + }, + "required": { + "conditionGroup": [ + { + "attribute": "action", + "type": "equals", + "value": "Move to Folder" + } + ] + } + }, + "groupEmailFolder": { + "visible": { + "conditionGroup": [ + { + "attribute": "action", + "type": "equals", + "value": "Move to Group Folder" + } + ] + }, + "required": { + "conditionGroup": [ + { + "attribute": "action", + "type": "equals", + "value": "Move to Group Folder" + } + ] + } + }, + "markAsRead": { + "visible": { + "conditionGroup": [ + { + "attribute": "parentType", + "type": "equals", + "value": "User" + } + ] + } + }, + "skipNotification": { + "visible": { + "conditionGroup": [ + { + "attribute": "parentType", + "type": "equals", + "value": "User" + } + ] + } + } + }, + "options": { + "action": [ + { + "conditionGroup": [ + { + "attribute": "isGlobal", + "type": "isTrue" + } + ], + "optionList": [ + "Skip" + ] + }, + { + "conditionGroup": [ + { + "attribute": "parentType", + "type": "equals", + "value": "User" + } + ], + "optionList": [ + "Skip", + "Move to Folder", + "None" + ] + }, + { + "conditionGroup": [ + { + "attribute": "parentType", + "type": "equals", + "value": "InboundEmail" + } + ], + "optionList": [ + "Skip", + "Move to Group Folder" + ] + }, + { + "conditionGroup": [], + "optionList": [ + "Skip" + ] + } + ] + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/InboundEmail.json b/application/Espo/Resources/metadata/logicDefs/InboundEmail.json new file mode 100644 index 0000000000..dfcc5813e8 --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/InboundEmail.json @@ -0,0 +1,59 @@ +{ + "fields": { + "smtpUsername": { + "required": { + "conditionGroup": [ + { + "type": "and", + "value": [ + { + "type": "isTrue", + "attribute": "useSmtp" + }, + { + "type": "isTrue", + "attribute": "smtpAuth" + } + ] + } + ] + } + }, + "fetchSince": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "useImap" + } + ] + }, + "readOnly": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "fetchData" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "useImap" + } + ] + } + }, + "isSystem": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/LeadCapture.json b/application/Espo/Resources/metadata/logicDefs/LeadCapture.json new file mode 100644 index 0000000000..f339c46a75 --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/LeadCapture.json @@ -0,0 +1,237 @@ +{ + "fields": { + "targetList": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "subscribeToTargetList" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "subscribeToTargetList" + } + ] + } + }, + "subscribeContactToTargetList": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "subscribeToTargetList" + } + ] + } + }, + "optInConfirmationLifetime": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "optInConfirmation" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "optInConfirmation" + } + ] + } + }, + "optInConfirmationSuccessMessage": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "optInConfirmation" + } + ] + } + }, + "createLeadBeforeOptInConfirmation": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "optInConfirmation" + } + ] + } + }, + "smtpAccount": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "optInConfirmation" + } + ] + } + }, + "skipOptInConfirmationIfSubscribed": { + "visible": { + "conditionGroup": [ + { + "type": "and", + "value": [ + { + "type": "isTrue", + "attribute": "optInConfirmation" + }, + { + "type": "isNotEmpty", + "attribute": "targetListId", + "data": { + "field": "targetList" + } + } + ] + } + ] + } + }, + "optInConfirmationEmailTemplate": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "optInConfirmation" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "optInConfirmation" + } + ] + } + }, + "apiKey": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + }, + "phoneNumberCountry": { + "visible": { + "conditionGroup": [ + { + "type": "contains", + "attribute": "fieldList", + "value": "phoneNumber" + } + ] + } + }, + "formSuccessText": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + }, + "formTitle": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + }, + "formTheme": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + }, + "formText": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + }, + "formSuccessRedirectUrl": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + }, + "formLanguage": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + }, + "formFrameAncestors": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + }, + "formCaptcha": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + } + }, + "panels": { + "form": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + }, + { + "type": "isTrue", + "attribute": "formEnabled" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/OAuthProvider.json b/application/Espo/Resources/metadata/logicDefs/OAuthProvider.json new file mode 100644 index 0000000000..5334e22906 --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/OAuthProvider.json @@ -0,0 +1,54 @@ +{ + "fields": { + "authorizationRedirectUri": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + }, + "clientId": { + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "isActive" + } + ] + } + }, + "clientSecret": { + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "isActive" + } + ] + } + }, + "authorizationEndpoint": { + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "isActive" + } + ] + } + }, + "tokenEndpoint": { + "required": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "isActive" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/Preferences.json b/application/Espo/Resources/metadata/logicDefs/Preferences.json new file mode 100644 index 0000000000..7f532297bd --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/Preferences.json @@ -0,0 +1,14 @@ +{ + "fields": { + "assignmentEmailNotificationsIgnoreEntityTypeList": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "receiveAssignmentEmailNotifications" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/Template.json b/application/Espo/Resources/metadata/logicDefs/Template.json new file mode 100644 index 0000000000..324097ad0e --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/Template.json @@ -0,0 +1,104 @@ +{ + "fields": { + "entityType": { + "readOnly": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + }, + "footer": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "printFooter" + } + ] + } + }, + "footerPosition": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "printFooter" + } + ] + } + }, + "header": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "printHeader" + } + ] + } + }, + "headerPosition": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "printHeader" + } + ] + } + }, + "body": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "entityType" + } + ] + } + }, + "pageWidth": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "pageFormat", + "value": "Custom" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "pageFormat", + "value": "Custom" + } + ] + } + }, + "pageHeight": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "pageFormat", + "value": "Custom" + } + ] + }, + "required": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "pageFormat", + "value": "Custom" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/User.json b/application/Espo/Resources/metadata/logicDefs/User.json new file mode 100644 index 0000000000..47ecd81970 --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/User.json @@ -0,0 +1,44 @@ +{ + "fields": { + "avatarColor": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "avatarId", + "value": null, + "data": { + "field": "avatar" + } + }, + { + "type": "in", + "attribute": "type", + "value": [ + "regular", + "admin", + "api" + ] + } + ] + } + } + }, + "options": { + "authMethod": [ + { + "optionList": [ + "ApiKey", + "Hmac" + ], + "conditionGroup": [ + { + "type": "equals", + "attribute": "type", + "value": "api" + } + ] + } + ] + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/Webhook.json b/application/Espo/Resources/metadata/logicDefs/Webhook.json new file mode 100644 index 0000000000..f30caca6bb --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/Webhook.json @@ -0,0 +1,24 @@ +{ + "fields": { + "event": { + "readOnly": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + }, + "secretKey": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "id" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/WorkingTimeCalendar.json b/application/Espo/Resources/metadata/logicDefs/WorkingTimeCalendar.json new file mode 100644 index 0000000000..fdccd8ba44 --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/WorkingTimeCalendar.json @@ -0,0 +1,84 @@ +{ + "fields": { + "weekday0TimeRanges": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "weekday0" + } + ] + } + }, + "weekday1TimeRanges": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "weekday1" + } + ] + } + }, + "weekday2TimeRanges": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "weekday2" + } + ] + } + }, + "weekday3TimeRanges": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "weekday3" + } + ] + } + }, + "weekday4TimeRanges": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "weekday4" + } + ] + } + }, + "weekday5TimeRanges": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "weekday5" + } + ] + } + }, + "weekday6TimeRanges": { + "visible": { + "conditionGroup": [ + { + "type": "isTrue", + "attribute": "weekday6" + } + ] + } + }, + "teams": { + "visible": { + "conditionGroup": [ + { + "type": "isNotEmpty", + "attribute": "teamsIds" + } + ] + } + } + } +} diff --git a/application/Espo/Resources/metadata/logicDefs/WorkingTimeRange.json b/application/Espo/Resources/metadata/logicDefs/WorkingTimeRange.json new file mode 100644 index 0000000000..605b9f7262 --- /dev/null +++ b/application/Espo/Resources/metadata/logicDefs/WorkingTimeRange.json @@ -0,0 +1,38 @@ +{ + "fields": { + "timeRanges": { + "visible": { + "conditionGroup": [ + { + "type": "equals", + "attribute": "type", + "value": "Working" + } + ] + } + }, + "users": { + "visible": { + "conditionGroup": [ + { + "type": "or", + "value": [ + { + "type": "isNotEmpty", + "attribute": "id" + }, + { + "type": "isNotEmpty", + "attribute": "usersIds" + }, + { + "type": "isEmpty", + "attribute": "calendarsIds" + } + ] + } + ] + } + } + } +} diff --git a/application/Espo/Tools/App/MetadataService.php b/application/Espo/Tools/App/MetadataService.php index c4beac001f..79938e0e93 100644 --- a/application/Espo/Tools/App/MetadataService.php +++ b/application/Espo/Tools/App/MetadataService.php @@ -92,6 +92,7 @@ class MetadataService unset($data->clientDefs->$scope); unset($data->entityAcl->$scope); unset($data->scopes->$scope); + unset($data->logicDefs->$scope); } } diff --git a/application/Espo/Tools/EntityManager/Rename/MetadataType.php b/application/Espo/Tools/EntityManager/Rename/MetadataType.php index 0339aab556..6b5fe04ed9 100644 --- a/application/Espo/Tools/EntityManager/Rename/MetadataType.php +++ b/application/Espo/Tools/EntityManager/Rename/MetadataType.php @@ -50,4 +50,6 @@ class MetadataType public const PDF_DEFS = 'pdfDefs'; public const FORMULA = 'formula'; + + public const LOGIC_DEFS = 'logicDefs'; } diff --git a/application/Espo/Tools/EntityManager/Rename/Renamer.php b/application/Espo/Tools/EntityManager/Rename/Renamer.php index fb15fa94d2..23ac817da7 100644 --- a/application/Espo/Tools/EntityManager/Rename/Renamer.php +++ b/application/Espo/Tools/EntityManager/Rename/Renamer.php @@ -75,6 +75,7 @@ class Renamer MetadataType::RECORD_DEFS, MetadataType::SCOPES, MetadataType::SELECT_DEFS, + MetadataType::LOGIC_DEFS, ]; private NameUtil $nameUtil; diff --git a/application/Espo/Tools/FieldManager/FieldManager.php b/application/Espo/Tools/FieldManager/FieldManager.php index 527a619435..29d5fd58fd 100644 --- a/application/Espo/Tools/FieldManager/FieldManager.php +++ b/application/Espo/Tools/FieldManager/FieldManager.php @@ -300,106 +300,95 @@ class FieldManager } $metadataToBeSaved = false; - $clientDefsToBeSet = false; + $logicDefsToBeSet = false; - $clientDefs = []; + $logicDefs = []; if (array_key_exists('dynamicLogicVisible', $fieldDefs)) { if (!is_null($fieldDefs['dynamicLogicVisible'])) { - $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); + $this->prepareLogicDefsFields($logicDefs, $name); - $clientDefs['dynamicLogic']['fields'][$name]['visible'] = $fieldDefs['dynamicLogicVisible']; + $logicDefs['fields'][$name]['visible'] = $fieldDefs['dynamicLogicVisible']; - $clientDefsToBeSet = true; - } else { - if ( - $this->metadata->get(['clientDefs', $scope, 'dynamicLogic', 'fields', $name, 'visible']) - ) { - $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); + $logicDefsToBeSet = true; + } else if ($this->metadata->get(['logicDefs', $scope, 'fields', $name, 'visible'])) { + $this->prepareLogicDefsFields($logicDefs, $name); - $clientDefs['dynamicLogic']['fields'][$name]['visible'] = null; - $clientDefsToBeSet = true; - } + $logicDefs['fields'][$name]['visible'] = null; + $logicDefsToBeSet = true; } } if (array_key_exists('dynamicLogicReadOnly', $fieldDefs)) { if (!is_null($fieldDefs['dynamicLogicReadOnly'])) { - $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); + $this->prepareLogicDefsFields($logicDefs, $name); - $clientDefs['dynamicLogic']['fields'][$name]['readOnly'] = $fieldDefs['dynamicLogicReadOnly']; - $clientDefsToBeSet = true; - } else { - if ( - $this->metadata->get(['clientDefs', $scope, 'dynamicLogic', 'fields', $name, 'readOnly']) - ) { - $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); + $logicDefs['fields'][$name]['readOnly'] = $fieldDefs['dynamicLogicReadOnly']; + $logicDefsToBeSet = true; + } else if ($this->metadata->get(['logicDefs', $scope, 'fields', $name, 'readOnly'])) { + $this->prepareLogicDefsFields($logicDefs, $name); - $clientDefs['dynamicLogic']['fields'][$name]['readOnly'] = null; + $logicDefs['fields'][$name]['readOnly'] = null; - $clientDefsToBeSet = true; - } + $logicDefsToBeSet = true; } } if (array_key_exists('dynamicLogicRequired', $fieldDefs)) { if (!is_null($fieldDefs['dynamicLogicRequired'])) { - $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); + $this->prepareLogicDefsFields($logicDefs, $name); - $clientDefs['dynamicLogic']['fields'][$name]['required'] = $fieldDefs['dynamicLogicRequired']; - $clientDefsToBeSet = true; - } else { - if ( - $this->metadata->get(['clientDefs', $scope, 'dynamicLogic', 'fields', $name, 'required']) - ) { - $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); + $logicDefs['fields'][$name]['required'] = $fieldDefs['dynamicLogicRequired']; + $logicDefsToBeSet = true; + } else if ($this->metadata->get(['logicDefs', $scope, 'fields', $name, 'required'])) { + $this->prepareLogicDefsFields($logicDefs, $name); - $clientDefs['dynamicLogic']['fields'][$name]['required'] = null; + $logicDefs['fields'][$name]['required'] = null; - $clientDefsToBeSet = true; - } + $logicDefsToBeSet = true; } } if (array_key_exists('dynamicLogicOptions', $fieldDefs)) { if (!is_null($fieldDefs['dynamicLogicOptions'])) { - $this->prepareClientDefsOptionsDynamicLogic($clientDefs, $name); + $this->prepareLogicDefsOptions($logicDefs, $name); - $clientDefs['dynamicLogic']['options'][$name] = $fieldDefs['dynamicLogicOptions']; + $logicDefs['options'][$name] = $fieldDefs['dynamicLogicOptions']; - $clientDefsToBeSet = true; + $logicDefsToBeSet = true; } else { - if ($this->metadata->get(['clientDefs', $scope, 'dynamicLogic', 'options', $name])) { - $this->prepareClientDefsOptionsDynamicLogic($clientDefs, $name); + if ($this->metadata->get(['logicDefs', $scope, 'options', $name])) { + $this->prepareLogicDefsOptions($logicDefs, $name); - $clientDefs['dynamicLogic']['options'][$name] = null; + $logicDefs['options'][$name] = null; - $clientDefsToBeSet = true; + $logicDefsToBeSet = true; } } } if (array_key_exists('dynamicLogicInvalid', $fieldDefs)) { if (!is_null($fieldDefs['dynamicLogicInvalid'])) { - $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); + $this->prepareLogicDefsFields($logicDefs, $name); - $clientDefs['dynamicLogic']['fields'][$name]['invalid'] = $fieldDefs['dynamicLogicInvalid']; - $clientDefsToBeSet = true; + $logicDefs['fields'][$name]['invalid'] = $fieldDefs['dynamicLogicInvalid']; + + $logicDefsToBeSet = true; } else { if ( - $this->metadata->get(['clientDefs', $scope, 'dynamicLogic', 'fields', $name, 'invalid']) + $this->metadata->get(['logicDefs', $scope, 'fields', $name, 'invalid']) ) { - $this->prepareClientDefsFieldsDynamicLogic($clientDefs, $name); + $this->prepareLogicDefsFields($logicDefs, $name); - $clientDefs['dynamicLogic']['fields'][$name]['invalid'] = null; + $logicDefs['fields'][$name]['invalid'] = null; - $clientDefsToBeSet = true; + $logicDefsToBeSet = true; } } } - if ($clientDefsToBeSet) { - $this->metadata->set('clientDefs', $scope, $clientDefs); + if ($logicDefsToBeSet) { + $this->metadata->set('logicDefs', $scope, $logicDefs); $metadataToBeSaved = true; } @@ -424,41 +413,21 @@ class FieldManager } /** - * @param array $clientDefs - * @param string $name + * @param array $logicDefs */ - private function prepareClientDefsFieldsDynamicLogic(&$clientDefs, $name): void + private function prepareLogicDefsFields(array &$logicDefs, string $name): void { - if (!array_key_exists('dynamicLogic', $clientDefs)) { - $clientDefs['dynamicLogic'] = []; - } - - if (!array_key_exists('fields', $clientDefs['dynamicLogic'])) { - $clientDefs['dynamicLogic']['fields'] = []; - } - - if (!array_key_exists($name, $clientDefs['dynamicLogic']['fields'])) { - $clientDefs['dynamicLogic']['fields'][$name] = []; - } + $logicDefs['fields'] ??= []; + $logicDefs['fields'][$name] ??= []; } /** - * @param array $clientDefs - * @param string $name + * @param array $logicDefs */ - private function prepareClientDefsOptionsDynamicLogic(&$clientDefs, $name): void + private function prepareLogicDefsOptions(array &$logicDefs, string $name): void { - if (!array_key_exists('dynamicLogic', $clientDefs)) { - $clientDefs['dynamicLogic'] = []; - } - - if (!array_key_exists('options', $clientDefs['dynamicLogic'])) { - $clientDefs['dynamicLogic']['options'] = []; - } - - if (!array_key_exists($name, $clientDefs['dynamicLogic']['options'])) { - $clientDefs['dynamicLogic']['options'][$name] = []; - } + $logicDefs['options'] ??= []; + $logicDefs['options'][$name] ??= []; } /** @@ -511,9 +480,9 @@ class FieldManager $this->metadata->delete('entityDefs', $scope, $unsets); - $this->metadata->delete('clientDefs', $scope, [ - "dynamicLogic.fields.$name", - "dynamicLogic.options.$name", + $this->metadata->delete('logicDefs', $scope, [ + "fields.$name", + "options.$name", ]); $this->metadata->save(); @@ -558,9 +527,9 @@ class FieldManager $this->metadata->delete('entityDefs', $scope, ['fields.' . $name]); - $this->metadata->delete('clientDefs', $scope, [ - 'dynamicLogic.fields.' . $name, - 'dynamicLogic.options.' . $name, + $this->metadata->delete('logicDefs', $scope, [ + "fields.$name", + "options.$name", ]); $this->metadata->save(); diff --git a/client/src/views/admin/field-manager/edit.js b/client/src/views/admin/field-manager/edit.js index 2aa4c1f198..ffc2038b2d 100644 --- a/client/src/views/admin/field-manager/edit.js +++ b/client/src/views/admin/field-manager/edit.js @@ -451,8 +451,8 @@ class FieldManagerEditView extends View { const promiseList = []; if (!defs.dynamicLogicVisibleDisabled) { - const isVisible = this.getMetadata() - .get(['clientDefs', this.scope, 'dynamicLogic', 'fields', this.field, 'visible']); + const isVisible = + this.getMetadata().get(['logicDefs', this.scope, 'fields', this.field, 'visible']); this.model.set( 'dynamicLogicVisible', @@ -472,8 +472,8 @@ class FieldManagerEditView extends View { const readOnly = this.getMetadata().get(['fields', this.type, 'readOnly']); if (!defs.dynamicLogicRequiredDisabled && !readOnly && hasRequired) { - const dynamicLogicRequired = this.getMetadata() - .get(['clientDefs', this.scope, 'dynamicLogic', 'fields', this.field, 'required']); + const dynamicLogicRequired = + this.getMetadata().get(['logicDefs', this.scope, 'fields', this.field, 'required']); this.model.set('dynamicLogicRequired', dynamicLogicRequired); @@ -489,7 +489,7 @@ class FieldManagerEditView extends View { if (!defs.dynamicLogicReadOnlyDisabled && !readOnly) { const dynamicLogicReadOnly = this.getMetadata() - .get(['clientDefs', this.scope, 'dynamicLogic', 'fields', this.field, 'readOnly']); + .get(['logicDefs', this.scope, 'fields', this.field, 'readOnly']); this.model.set('dynamicLogicReadOnly', dynamicLogicReadOnly); @@ -506,8 +506,8 @@ class FieldManagerEditView extends View { const typeDynamicLogicOptions = this.getMetadata().get(['fields', this.type, 'dynamicLogicOptions']); if (typeDynamicLogicOptions && !defs.dynamicLogicOptionsDisabled) { - const dynamicLogicOptions = this.getMetadata() - .get(['clientDefs', this.scope, 'dynamicLogic', 'options', this.field]); + const dynamicLogicOptions = + this.getMetadata().get(['logicDefs', this.scope, 'options', this.field]); this.model.set('dynamicLogicOptions', dynamicLogicOptions); @@ -522,8 +522,8 @@ class FieldManagerEditView extends View { } if (!defs.dynamicLogicInvalidDisabled && !readOnly) { - const dynamicLogicInvalid = this.getMetadata() - .get(['clientDefs', this.scope, 'dynamicLogic', 'fields', this.field, 'invalid']); + const dynamicLogicInvalid = + this.getMetadata().get(['logicDefs', this.scope, 'fields', this.field, 'invalid']); this.model.set('dynamicLogicInvalid', dynamicLogicInvalid); diff --git a/client/src/views/record/detail.js b/client/src/views/record/detail.js index 3413ca2d92..170af961bd 100644 --- a/client/src/views/record/detail.js +++ b/client/src/views/record/detail.js @@ -2062,8 +2062,7 @@ class DetailRecordView extends BaseRecordView { this.initDependency(); - const dynamicLogic = Espo.Utils.clone( - this.getMetadata().get(['clientDefs', this.entityType, 'dynamicLogic']) || {}); + const dynamicLogic = {...this.getMetadata().get(`logicDefs.${this.entityType}`, {})}; this.dynamicLogicDefs = _.extend(dynamicLogic, this.dynamicLogicDefs); diff --git a/schema/metadata/app/export.json b/schema/metadata/app/export.json index a05a6321c5..06e0469c68 100644 --- a/schema/metadata/app/export.json +++ b/schema/metadata/app/export.json @@ -68,7 +68,7 @@ "properties": { "visible": { "description": "Conditions making the parameter visible.", - "$ref": "./../clientDefs.json#/definitions/dynamicLogicVisible" + "$ref": "./../logicDefs.json#/definitions/dynamicLogicVisible" } } } diff --git a/schema/metadata/authenticationMethods.json b/schema/metadata/authenticationMethods.json index 088f74479f..513bfc9f92 100644 --- a/schema/metadata/authenticationMethods.json +++ b/schema/metadata/authenticationMethods.json @@ -80,16 +80,16 @@ "properties": { "visible": { "description": "Conditions making the field visible.", - "$ref": "./clientDefs.json#/definitions/dynamicLogicVisible" + "$ref": "./logicDefs.json#/definitions/dynamicLogicVisible" }, "required": { - "$ref": "./clientDefs.json#/definitions/dynamicLogicRequired" + "$ref": "./logicDefs.json#/definitions/dynamicLogicRequired" }, "readOnly": { - "$ref": "./clientDefs.json#/definitions/dynamicLogicReadOnly" + "$ref": "./logicDefs.json#/definitions/dynamicLogicReadOnly" }, "invalid": { - "$ref": "./clientDefs.json#/definitions/dynamicLogicInvalid" + "$ref": "./logicDefs.json#/definitions/dynamicLogicInvalid" } } } diff --git a/schema/metadata/clientDefs.json b/schema/metadata/clientDefs.json index 2d63defef3..7293d541dd 100644 --- a/schema/metadata/clientDefs.json +++ b/schema/metadata/clientDefs.json @@ -746,74 +746,6 @@ "isExpandedByDefault": { "description": "Actual for category scopes (e.g. DocumentFolder). If true, then by default it will be in expanded mode.", "type": "boolean" - }, - "dynamicLogic": { - "description": "Dynamic logic definitions making a form dynamic.", - "type": "object", - "properties": { - "fields": { - "type": "object", - "description": "Fields.", - "additionalProperties": { - "type": "object", - "description": "A field name.", - "properties": { - "visible": { - "description": "Conditions making the field visible.", - "$ref": "#/definitions/dynamicLogicVisible" - }, - "required": { - "$ref": "#/definitions/dynamicLogicRequired" - }, - "readOnly": { - "$ref": "#/definitions/dynamicLogicReadOnly" - }, - "invalid": { - "$ref": "#/definitions/dynamicLogicInvalid" - } - } - } - }, - "panels": { - "type": "object", - "description": "Panels.", - "additionalProperties": { - "type": "object", - "description": "A panel name.", - "properties": { - "visible": { - "description": "Conditions making the panel visible.", - "$ref": "#/definitions/dynamicLogicVisible" - } - } - } - }, - "options": { - "type": "object", - "description": "Enum options.", - "additionalProperties": { - "type": "array", - "description": "A field name.", - "items": { - "type": "object", - "properties": { - "optionList": { - "type": "array", - "items": {"type": "string"}, - "description": "Options." - }, - "conditionGroup": { - "type": "array", - "description": "An AND where clause.", - "items": { - "$ref": "#/definitions/dynamicLogicItem" - } - } - } - } - } - } - } } }, "definitions": { @@ -910,216 +842,6 @@ } } }, - "dynamicLogicVisible": { - "type": "object", - "description": "Conditions making the element visible.", - "properties": { - "conditionGroup": { - "description": "An AND where clause.", - "type": "array", - "items": { - "$ref": "#/definitions/dynamicLogicItem" - } - } - } - }, - "dynamicLogicRequired": { - "type": "object", - "description": "Conditions making the field required.", - "properties": { - "conditionGroup": { - "type": "array", - "description": "An AND where clause.", - "items": { - "$ref": "#/definitions/dynamicLogicItem" - } - } - } - }, - "dynamicLogicReadOnly": { - "type": "object", - "description": "Conditions making the field read-only.", - "properties": { - "conditionGroup": { - "type": "array", - "description": "An AND where clause.", - "items": { - "$ref": "#/definitions/dynamicLogicItem" - } - } - } - }, - "dynamicLogicInvalid": { - "type": "object", - "description": "Conditions making the field invalid.", - "properties": { - "conditionGroup": { - "type": "array", - "description": "An AND where clause.", - "items": { - "$ref": "#/definitions/dynamicLogicItem" - } - } - } - }, - "dynamicLogicItem": { - "type": "object", - "description": "A logic node.", - "anyOf": [ - { - "if": { - "properties": { - "type": { - "anyOf": [ - {"const": "and"}, - {"const": "or"} - ] - } - } - }, - "then": { - "properties": { - "value": { - "type": "array", - "description": "Sub-items.", - "items": { - "$ref": "#/definitions/dynamicLogicItem" - } - } - }, - "required": ["type", "value"] - } - }, - { - "if": { - "properties": { - "type": { - "anyOf": [ - {"const": "not"} - ] - } - } - }, - "then": { - "properties": { - "value": { - "type": "object", - "$ref": "#/definitions/dynamicLogicItem" - } - }, - "required": ["type", "value"] - } - }, - { - "if": { - "properties": { - "type": { - "anyOf": [ - {"const": "equals"}, - {"const": "notEquals"}, - {"const": "greaterThan"}, - {"const": "lessThan"}, - {"const": "greaterThanOrEquals"}, - {"const": "lessThanOrEquals"}, - {"const": "isEmpty"}, - {"const": "isNotEmpty"}, - {"const": "isTrue"}, - {"const": "isFalse"}, - {"const": "in"}, - {"const": "notIn"}, - {"const": "isToday"}, - {"const": "inFuture"}, - {"const": "inPast"}, - {"const": "contains"}, - {"const": "notContains"}, - {"const": "has"}, - {"const": "notHas"}, - {"const": "startsWith"}, - {"const": "endsWith"}, - {"const": "matches"} - ] - } - } - }, - "then": { - "properties": { - "value": { - "description": "A value.", - "anyOf": [ - {"type": "string"}, - {"type": "boolean"}, - {"type": "integer"}, - {"type": "integer"}, - {"type": "number"}, - {"type": "null"}, - { - "type": "array", - "items": {"type": "string"} - }, - { - "type": "array", - "items": {"type": "integer"} - }, - { - "type": "array", - "items": {"type": "number"} - } - ] - }, - "attribute": { - "type": "string", - "description": "An attribute." - } - }, - "required": ["type", "attribute"] - } - } - ], - "properties": { - "type": { - "description": "A type.", - "enum": [ - "and", - "or", - "not", - "equals", - "notEquals", - "greaterThan", - "lessThan", - "greaterThanOrEquals", - "lessThanOrEquals", - "isEmpty", - "isNotEmpty", - "isTrue", - "isFalse", - "in", - "notIn", - "isToday", - "inFuture", - "inPast", - "contains", - "notContains", - "has", - "notHas", - "startsWith", - "endsWith", - "matches" - ] - }, - "data": { - "type": "object", - "description": "Additional data. Not used for logic.", - "additionalProperties": true, - "properties": { - "field": { - "type": "string", - "description": "A field." - } - } - } - }, - "required": ["type"] - }, "actionDefs": { "type": "object", "properties": { diff --git a/schema/metadata/logicDefs.json b/schema/metadata/logicDefs.json new file mode 100644 index 0000000000..0eb098702c --- /dev/null +++ b/schema/metadata/logicDefs.json @@ -0,0 +1,282 @@ +{ + "$schema": "https://json-schema.org/draft/2020-12/schema", + "$id": "https://www.espocrm.com/schema/metadata/clientDefs.json", + "title": "clientDefs", + "description": "Dynamic logic for entity types.", + "type": "object", + "properties": { + "fields": { + "type": "object", + "description": "Fields.", + "additionalProperties": { + "type": "object", + "description": "A field name.", + "properties": { + "visible": { + "$ref": "#/definitions/dynamicLogicVisible" + }, + "required": { + "$ref": "#/definitions/dynamicLogicRequired" + }, + "readOnly": { + "$ref": "#/definitions/dynamicLogicReadOnly" + }, + "invalid": { + "$ref": "#/definitions/dynamicLogicInvalid" + } + } + } + }, + "panels": { + "type": "object", + "description": "Panels.", + "additionalProperties": { + "type": "object", + "description": "A panel name.", + "properties": { + "visible": { + "description": "Conditions making the panel visible.", + "$ref": "#/definitions/dynamicLogicVisible" + } + } + } + }, + "options": { + "type": "object", + "description": "Enum options.", + "additionalProperties": { + "type": "array", + "description": "A field name.", + "items": { + "type": "object", + "properties": { + "optionList": { + "type": "array", + "items": {"type": "string"}, + "description": "Options." + }, + "conditionGroup": { + "type": "array", + "description": "An AND where clause.", + "items": { + "$ref": "#/definitions/dynamicLogicItem" + } + } + } + } + } + } + }, + "definitions": { + "dynamicLogicVisible": { + "type": "object", + "description": "Conditions making the element visible.", + "properties": { + "conditionGroup": { + "description": "An AND where clause.", + "type": "array", + "items": { + "$ref": "#/definitions/dynamicLogicItem" + } + } + } + }, + "dynamicLogicRequired": { + "type": "object", + "description": "Conditions making the field required.", + "properties": { + "conditionGroup": { + "type": "array", + "description": "An AND where clause.", + "items": { + "$ref": "#/definitions/dynamicLogicItem" + } + } + } + }, + "dynamicLogicReadOnly": { + "type": "object", + "description": "Conditions making the field read-only.", + "properties": { + "conditionGroup": { + "type": "array", + "description": "An AND where clause.", + "items": { + "$ref": "#/definitions/dynamicLogicItem" + } + } + } + }, + "dynamicLogicInvalid": { + "type": "object", + "description": "Conditions making the field invalid.", + "properties": { + "conditionGroup": { + "type": "array", + "description": "An AND where clause.", + "items": { + "$ref": "#/definitions/dynamicLogicItem" + } + } + } + }, + "dynamicLogicItem": { + "type": "object", + "description": "A logic node.", + "anyOf": [ + { + "if": { + "properties": { + "type": { + "anyOf": [ + {"const": "and"}, + {"const": "or"} + ] + } + } + }, + "then": { + "properties": { + "value": { + "type": "array", + "description": "Sub-items.", + "items": { + "$ref": "#/definitions/dynamicLogicItem" + } + } + }, + "required": ["type", "value"] + } + }, + { + "if": { + "properties": { + "type": { + "anyOf": [ + {"const": "not"} + ] + } + } + }, + "then": { + "properties": { + "value": { + "type": "object", + "$ref": "#/definitions/dynamicLogicItem" + } + }, + "required": ["type", "value"] + } + }, + { + "if": { + "properties": { + "type": { + "anyOf": [ + {"const": "equals"}, + {"const": "notEquals"}, + {"const": "greaterThan"}, + {"const": "lessThan"}, + {"const": "greaterThanOrEquals"}, + {"const": "lessThanOrEquals"}, + {"const": "isEmpty"}, + {"const": "isNotEmpty"}, + {"const": "isTrue"}, + {"const": "isFalse"}, + {"const": "in"}, + {"const": "notIn"}, + {"const": "isToday"}, + {"const": "inFuture"}, + {"const": "inPast"}, + {"const": "contains"}, + {"const": "notContains"}, + {"const": "has"}, + {"const": "notHas"}, + {"const": "startsWith"}, + {"const": "endsWith"}, + {"const": "matches"} + ] + } + } + }, + "then": { + "properties": { + "value": { + "description": "A value.", + "anyOf": [ + {"type": "string"}, + {"type": "boolean"}, + {"type": "integer"}, + {"type": "integer"}, + {"type": "number"}, + {"type": "null"}, + { + "type": "array", + "items": {"type": "string"} + }, + { + "type": "array", + "items": {"type": "integer"} + }, + { + "type": "array", + "items": {"type": "number"} + } + ] + }, + "attribute": { + "type": "string", + "description": "An attribute." + } + }, + "required": ["type", "attribute"] + } + } + ], + "properties": { + "type": { + "description": "A type.", + "enum": [ + "and", + "or", + "not", + "equals", + "notEquals", + "greaterThan", + "lessThan", + "greaterThanOrEquals", + "lessThanOrEquals", + "isEmpty", + "isNotEmpty", + "isTrue", + "isFalse", + "in", + "notIn", + "isToday", + "inFuture", + "inPast", + "contains", + "notContains", + "has", + "notHas", + "startsWith", + "endsWith", + "matches" + ] + }, + "data": { + "type": "object", + "description": "Additional data. Not used for logic.", + "additionalProperties": true, + "properties": { + "field": { + "type": "string", + "description": "A field." + } + } + } + }, + "required": ["type"] + } + } +}