dynamic logic move

This commit is contained in:
Yuri Kuznetsov
2025-04-07 15:37:04 +03:00
parent 601cf8fdfd
commit 1bfc8a2b38
55 changed files with 1855 additions and 1658 deletions
+19
View File
@@ -1386,6 +1386,25 @@
</SchemaInfo>
</value>
</entry>
<entry key="metadata/logicDefs">
<value>
<SchemaInfo>
<option name="generatedName" value="New Schema" />
<option name="name" value="metadata/logicDefs" />
<option name="relativePathToSchema" value="schema/metadata/logicDefs.json" />
<option name="schemaVersion" value="JSON Schema version 7" />
<option name="patterns">
<list>
<Item>
<option name="pattern" value="true" />
<option name="path" value="*/metadata/logicDefs/*.json" />
<option name="mappingKind" value="Pattern" />
</Item>
</list>
</option>
</SchemaInfo>
</value>
</entry>
<entry key="metadata/notificationDefs">
<value>
<SchemaInfo>
+6
View File
@@ -82,6 +82,12 @@
],
"url": "./schema/metadata/integrations.json"
},
{
"fileMatch": [
"*/metadata/logicDefs/*.json"
],
"url": "./schema/metadata/logicDefs.json"
},
{
"fileMatch": [
"*/metadata/notificationDefs/*.json"
@@ -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);
}
}
}
@@ -0,0 +1,162 @@
<?php
/************************************************************************
* This file is part of EspoCRM.
*
* EspoCRM Open Source CRM application.
* Copyright (C) 2014-2025 Yurii Kuznietsov, Taras Machyshyn, Oleksii Avramenko
* Website: https://www.espocrm.com
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program 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 Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://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 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<string, stdClass> $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<string, stdClass> $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<string, stdClass[]> $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;
}
}
}
}
@@ -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"
}
@@ -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"
}
]
}
}
}
}
}
@@ -104,20 +104,6 @@
"filter": "open"
},
"allowInternalNotes": true,
"dynamicLogic": {
"fields": {
"number": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
}
}
}
},
"additionalLayouts": {
"detailPortal": {
"type": "detail"
@@ -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"
}
@@ -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"
@@ -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"
}
@@ -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"
}
@@ -46,21 +46,6 @@
"checkVisibilityFunction": "isCompleteAvailable"
}
],
"dynamicLogic": {
"fields": {
"dateCompleted": {
"visible": {
"conditionGroup": [
{
"type": "equals",
"attribute": "status",
"value": "Completed"
}
]
}
}
}
},
"filterList": [
"actual",
{
@@ -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"]
}
]
}
}
}
}
@@ -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"
}
]
}
}
}
}
@@ -0,0 +1,14 @@
{
"fields": {
"number": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
}
}
}
}
@@ -0,0 +1,27 @@
{
"fields": {
"title": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "accountId"
}
]
}
},
"portalUser": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "portalUserId",
"data": {
"field": "portalUser"
}
}
]
}
}
}
}
@@ -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"
]
}
]
}
]
}
}
@@ -0,0 +1,15 @@
{
"fields": {
"lastStage": {
"visible": {
"conditionGroup": [
{
"type": "equals",
"attribute": "stage",
"value": "Closed Lost"
}
]
}
}
}
}
@@ -0,0 +1,24 @@
{
"fields": {
"entryCount": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
}
},
"optedOutCount": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
}
}
}
}
@@ -0,0 +1,15 @@
{
"fields": {
"dateCompleted": {
"visible": {
"conditionGroup": [
{
"type": "equals",
"attribute": "status",
"value": "Completed"
}
]
}
}
}
}
@@ -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"
]
}
@@ -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":[
],
@@ -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"
@@ -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"
]
}
]
}
}
]
}
@@ -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": {
@@ -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": [
{
@@ -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"
}
]
}
}
}
}
}
@@ -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"
}
@@ -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"
}
@@ -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"
}
@@ -14,29 +14,5 @@
}
]
}
},
"dynamicLogic": {
"fields": {
"event": {
"readOnly": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
}
},
"secretKey": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
}
}
}
}
}
@@ -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"
}
]
}
}
}
}
}
@@ -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"
]
@@ -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"
}
]
}
}
}
}
@@ -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"
}
]
}
}
}
}
@@ -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"
]
}
]
}
}
@@ -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"
}
]
}
}
}
}
@@ -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"
}
]
}
}
}
}
@@ -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"
}
]
}
}
}
}
@@ -0,0 +1,14 @@
{
"fields": {
"assignmentEmailNotificationsIgnoreEntityTypeList": {
"visible": {
"conditionGroup": [
{
"type": "isTrue",
"attribute": "receiveAssignmentEmailNotifications"
}
]
}
}
}
}
@@ -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"
}
]
}
}
}
}
@@ -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"
}
]
}
]
}
}
@@ -0,0 +1,24 @@
{
"fields": {
"event": {
"readOnly": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
}
},
"secretKey": {
"visible": {
"conditionGroup": [
{
"type": "isNotEmpty",
"attribute": "id"
}
]
}
}
}
}
@@ -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"
}
]
}
}
}
}
@@ -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"
}
]
}
]
}
}
}
}
@@ -92,6 +92,7 @@ class MetadataService
unset($data->clientDefs->$scope);
unset($data->entityAcl->$scope);
unset($data->scopes->$scope);
unset($data->logicDefs->$scope);
}
}
@@ -50,4 +50,6 @@ class MetadataType
public const PDF_DEFS = 'pdfDefs';
public const FORMULA = 'formula';
public const LOGIC_DEFS = 'logicDefs';
}
@@ -75,6 +75,7 @@ class Renamer
MetadataType::RECORD_DEFS,
MetadataType::SCOPES,
MetadataType::SELECT_DEFS,
MetadataType::LOGIC_DEFS,
];
private NameUtil $nameUtil;
@@ -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<string, mixed> $clientDefs
* @param string $name
* @param array<string, mixed> $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<string, mixed> $clientDefs
* @param string $name
* @param array<string, mixed> $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();
+9 -9
View File
@@ -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);
+1 -2
View File
@@ -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);
+1 -1
View File
@@ -68,7 +68,7 @@
"properties": {
"visible": {
"description": "Conditions making the parameter visible.",
"$ref": "./../clientDefs.json#/definitions/dynamicLogicVisible"
"$ref": "./../logicDefs.json#/definitions/dynamicLogicVisible"
}
}
}
+4 -4
View File
@@ -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"
}
}
}
-278
View File
@@ -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": {
+282
View File
@@ -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"]
}
}
}