diff --git a/application/Espo/Classes/FieldProcessing/Email/UserColumnsLoader.php b/application/Espo/Classes/FieldProcessing/Email/UserColumnsLoader.php index f285e35eac..2682e80775 100644 --- a/application/Espo/Classes/FieldProcessing/Email/UserColumnsLoader.php +++ b/application/Espo/Classes/FieldProcessing/Email/UserColumnsLoader.php @@ -73,12 +73,18 @@ class UserColumnsLoader implements Loader return; } - $entity->set([ + $values = [ Email::USERS_COLUMN_IS_READ => $emailUser->get(Email::USERS_COLUMN_IS_READ), Email::USERS_COLUMN_IS_IMPORTANT => $emailUser->get(Email::USERS_COLUMN_IS_IMPORTANT), Email::USERS_COLUMN_IN_TRASH => $emailUser->get(Email::USERS_COLUMN_IN_TRASH), Email::USERS_COLUMN_IN_ARCHIVE => $emailUser->get(Email::USERS_COLUMN_IN_ARCHIVE), 'isUsersSent' => $entity->getSentBy()?->getId() === $this->user->getId(), - ]); + ]; + + $entity->setMultiple($values); + + foreach ($values as $key => $value) { + $entity->setFetched($key, $value); + } } } diff --git a/application/Espo/Classes/RecordHooks/Email/BeforeUpdate.php b/application/Espo/Classes/RecordHooks/Email/BeforeUpdate.php index 8af5b4ee73..b522922afc 100644 --- a/application/Espo/Classes/RecordHooks/Email/BeforeUpdate.php +++ b/application/Espo/Classes/RecordHooks/Email/BeforeUpdate.php @@ -31,8 +31,10 @@ namespace Espo\Classes\RecordHooks\Email; use Espo\Core\Mail\EmailSender; use Espo\Core\Name\Field; +use Espo\Core\ORM\Type\FieldType; use Espo\Core\Record\Hook\SaveHook; use Espo\Core\Utils\FieldUtil; +use Espo\Core\Utils\Metadata; use Espo\Core\Utils\SystemUser; use Espo\Entities\Email; use Espo\Entities\User; @@ -54,7 +56,8 @@ class BeforeUpdate implements SaveHook public function __construct( private User $user, private EntityManager $entityManager, - private FieldUtil $fieldUtil + private FieldUtil $fieldUtil, + private Metadata $metadata, ) {} public function process(Entity $entity): void @@ -125,18 +128,24 @@ class BeforeUpdate implements SaveHook private function clearEntityForUpdate(Email $email): void { - $fieldDefsList = $this->entityManager + $entityDefs = $this->entityManager ->getDefs() - ->getEntity(Email::ENTITY_TYPE) - ->getFieldList(); + ->getEntity(Email::ENTITY_TYPE); - foreach ($fieldDefsList as $fieldDefs) { + foreach ($entityDefs->getFieldList() as $fieldDefs) { $field = $fieldDefs->getName(); if ($fieldDefs->getParam('isCustom')) { continue; } + if ( + $fieldDefs->getType() === FieldType::LINK_MULTIPLE && + $this->metadata->get("entityDefs.Email.links.$field.isCustom") + ) { + continue; + } + if (in_array($field, $this->allowedForUpdateFieldList)) { continue; } @@ -144,7 +153,9 @@ class BeforeUpdate implements SaveHook $attributeList = $this->fieldUtil->getAttributeList(Email::ENTITY_TYPE, $field); foreach ($attributeList as $attribute) { - $email->clear($attribute); + if ($email->isAttributeChanged($attribute) && $email->isAttributeWritten($attribute)) { + $email->set($attribute, $email->getFetched($attribute)); + } } } } diff --git a/application/Espo/Core/Formula/Functions/RecordGroup/CountType.php b/application/Espo/Core/Formula/Functions/RecordGroup/CountType.php index a8292a5795..ed760929ab 100644 --- a/application/Espo/Core/Formula/Functions/RecordGroup/CountType.php +++ b/application/Espo/Core/Formula/Functions/RecordGroup/CountType.php @@ -36,6 +36,7 @@ use Espo\Core\Formula\Exceptions\Error; use Espo\Core\Formula\Functions\BaseFunction; use Espo\Core\Formula\Functions\RecordGroup\Util\FindQueryUtil; use Espo\Core\Di; +use Espo\Core\Select\Primary\Filters\All; use Espo\Core\Select\SelectBuilderFactory; /** @@ -68,6 +69,7 @@ class CountType extends BaseFunction implements $builder = $this->injectableFactory->create(SelectBuilderFactory::class) ->create() ->forUser($this->user) + ->withPrimaryFilter(All::NAME) ->from($entityType); (new FindQueryUtil())->applyFilter($builder, $filter, 2); diff --git a/application/Espo/Core/Formula/Functions/RecordGroup/ExistsType.php b/application/Espo/Core/Formula/Functions/RecordGroup/ExistsType.php index 825e0cafc2..12d98357c5 100644 --- a/application/Espo/Core/Formula/Functions/RecordGroup/ExistsType.php +++ b/application/Espo/Core/Formula/Functions/RecordGroup/ExistsType.php @@ -36,6 +36,7 @@ use Espo\Core\Formula\Exceptions\Error; use Espo\Core\Formula\Functions\BaseFunction; use Espo\Core\Di; use Espo\Core\Formula\Functions\RecordGroup\Util\FindQueryUtil; +use Espo\Core\Select\Primary\Filters\All; use Espo\Core\Select\SelectBuilderFactory; /** @@ -68,6 +69,7 @@ class ExistsType extends BaseFunction implements $builder = $this->injectableFactory->create(SelectBuilderFactory::class) ->create() ->forUser($this->user) + ->withPrimaryFilter(All::NAME) ->from($entityType); (new FindQueryUtil())->applyFilter($builder, $filter, 2); diff --git a/application/Espo/Core/Formula/Functions/RecordGroup/FindManyType.php b/application/Espo/Core/Formula/Functions/RecordGroup/FindManyType.php index f614c96552..4d4c21e78f 100644 --- a/application/Espo/Core/Formula/Functions/RecordGroup/FindManyType.php +++ b/application/Espo/Core/Formula/Functions/RecordGroup/FindManyType.php @@ -38,6 +38,7 @@ use Espo\Core\Formula\Exceptions\Error as FormulaError; use Espo\Core\Formula\Exceptions\TooFewArguments; use Espo\Core\Formula\Func; use Espo\Core\Formula\Functions\RecordGroup\Util\FindQueryUtil; +use Espo\Core\Select\Primary\Filters\All; use Espo\Core\Select\SelectBuilderFactory; use Espo\ORM\Entity; use Espo\ORM\EntityManager; @@ -92,6 +93,7 @@ class FindManyType implements Func $builder = $this->selectBuilderFactory ->create() + ->withPrimaryFilter(All::NAME) ->from($entityType); $whereClause = []; diff --git a/application/Espo/Core/Formula/Functions/RecordGroup/FindOneType.php b/application/Espo/Core/Formula/Functions/RecordGroup/FindOneType.php index b8d504b2ae..77e969ce1a 100644 --- a/application/Espo/Core/Formula/Functions/RecordGroup/FindOneType.php +++ b/application/Espo/Core/Formula/Functions/RecordGroup/FindOneType.php @@ -36,6 +36,7 @@ use Espo\Core\Formula\Exceptions\Error as FormulaError; use Espo\Core\Formula\Functions\BaseFunction; use Espo\Core\Di; use Espo\Core\Formula\Functions\RecordGroup\Util\FindQueryUtil; +use Espo\Core\Select\Primary\Filters\All; use Espo\Core\Select\SelectBuilderFactory; use Espo\ORM\Name\Attribute; use Espo\ORM\Query\Part\Order; @@ -65,6 +66,7 @@ class FindOneType extends BaseFunction implements $builder = $this->injectableFactory->create(SelectBuilderFactory::class) ->create() ->forUser($this->user) + ->withPrimaryFilter(All::NAME) ->from($entityType); $whereClause = []; diff --git a/application/Espo/Core/Formula/Functions/RecordGroup/FindRelatedManyType.php b/application/Espo/Core/Formula/Functions/RecordGroup/FindRelatedManyType.php index 40f946e621..b8692db001 100644 --- a/application/Espo/Core/Formula/Functions/RecordGroup/FindRelatedManyType.php +++ b/application/Espo/Core/Formula/Functions/RecordGroup/FindRelatedManyType.php @@ -41,6 +41,7 @@ use Espo\Core\Formula\ArgumentList; use Espo\Core\Formula\Functions\BaseFunction; use Espo\Core\Di; use Espo\Core\Select\Helpers\RandomStringGenerator; +use Espo\Core\Select\Primary\Filters\All; use Espo\Core\Select\SelectBuilderFactory; use Espo\ORM\Defs\Params\RelationParam; use Espo\ORM\Name\Attribute; @@ -165,6 +166,7 @@ class FindRelatedManyType extends BaseFunction implements $builder = $this->injectableFactory->create(SelectBuilderFactory::class) ->create() ->forUser($this->user) + ->withPrimaryFilter(All::NAME) ->from($foreignEntityType); $whereClause = []; diff --git a/application/Espo/Core/Formula/Functions/RecordGroup/FindRelatedOneType.php b/application/Espo/Core/Formula/Functions/RecordGroup/FindRelatedOneType.php index 74c48cf87b..50eb14f230 100644 --- a/application/Espo/Core/Formula/Functions/RecordGroup/FindRelatedOneType.php +++ b/application/Espo/Core/Formula/Functions/RecordGroup/FindRelatedOneType.php @@ -32,6 +32,7 @@ namespace Espo\Core\Formula\Functions\RecordGroup; use Espo\Core\Exceptions\BadRequest; use Espo\Core\Exceptions\Forbidden; use Espo\Core\ORM\Entity as CoreEntity; +use Espo\Core\Select\Primary\Filters\All; use Espo\Core\Select\SelectBuilderFactory; use Espo\ORM\Defs\Params\RelationParam; use Espo\ORM\Name\Attribute; @@ -151,6 +152,7 @@ class FindRelatedOneType extends BaseFunction implements $builder = $this->injectableFactory->create(SelectBuilderFactory::class) ->create() ->forUser($this->user) + ->withPrimaryFilter(All::NAME) ->from($foreignEntityType); $whereClause = []; diff --git a/application/Espo/Core/ORM/Entity.php b/application/Espo/Core/ORM/Entity.php index 878fd05a92..99dfd9260f 100644 --- a/application/Espo/Core/ORM/Entity.php +++ b/application/Espo/Core/ORM/Entity.php @@ -95,7 +95,7 @@ class Entity extends BaseEntity throw new LogicException("No entity-manager."); } - $toSetFetched = !$this->isNew() && !$this->hasFetched($idAttribute); + $toSetFetched = !$this->isNew() && !$this->isAttributeChanged($idAttribute); if (!$parentId || !$parentType) { /** @noinspection PhpRedundantOptionalArgumentInspection */ diff --git a/application/Espo/Core/Utils/Metadata/AdditionalBuilder/LogicDefsBc.php b/application/Espo/Core/Utils/Metadata/AdditionalBuilder/LogicDefsBc.php index ecc87bc51e..5b176bf669 100644 --- a/application/Espo/Core/Utils/Metadata/AdditionalBuilder/LogicDefsBc.php +++ b/application/Espo/Core/Utils/Metadata/AdditionalBuilder/LogicDefsBc.php @@ -129,6 +129,12 @@ class LogicDefsBc implements AdditionalBuilder $item = $subDefs->$subKey; $logicDefs->$key ??= (object) []; + + // Fix if corrupted. + if (is_array($logicDefs->$key)) { + $logicDefs->$key = (object) []; + } + $logicDefs->$key->$name ??= (object) []; $logicDefs->$key->$name->$subKey = $item !== null ? diff --git a/application/Espo/Entities/Email.php b/application/Espo/Entities/Email.php index da2d043e9b..c84e11a872 100644 --- a/application/Espo/Entities/Email.php +++ b/application/Espo/Entities/Email.php @@ -126,6 +126,24 @@ class Email extends Entity return parent::has($attribute); } + public function getFetched(string $attribute): mixed + { + if ($attribute === 'subject') { + return $this->getFetched(Field::NAME); + } + + return parent::getFetched($attribute); + } + + public function isAttributeChanged(string $name): bool + { + if ($name === 'subject') { + $name = Field::NAME; + } + + return parent::isAttributeChanged($name); + } + /** @noinspection PhpUnused */ protected function _setSubject(?string $value): void { diff --git a/application/Espo/Modules/Crm/Resources/layouts/Call/detailSmall.json b/application/Espo/Modules/Crm/Resources/layouts/Call/detailSmall.json index 0dd6c0167f..2d91852cd1 100644 --- a/application/Espo/Modules/Crm/Resources/layouts/Call/detailSmall.json +++ b/application/Espo/Modules/Crm/Resources/layouts/Call/detailSmall.json @@ -1,15 +1,14 @@ [ { - "label":"", "rows":[ - [{"name":"name", "fullWidth": true}], + [{"name":"name"}], [{"name":"status"}, {"name":"direction"}], - [{"name":"dateStart", "fullWidth": true}], - [{"name":"duration", "fullWidth": true}], - [{"name":"dateEnd", "fullWidth": true}], - [{"name":"parent", "fullWidth": true}], - [{"name":"reminders", "fullWidth": true}], - [{"name":"description", "fullWidth": true}] + [{"name":"dateStart"}], + [{"name":"duration"}, false], + [{"name":"dateEnd"}], + [{"name":"parent"}], + [{"name":"reminders"}], + [{"name":"description"}] ] } -] \ No newline at end of file +] diff --git a/application/Espo/Modules/Crm/Resources/layouts/Case/detailSmall.json b/application/Espo/Modules/Crm/Resources/layouts/Case/detailSmall.json index d7b5b5bfe1..9c43f5d3e2 100644 --- a/application/Espo/Modules/Crm/Resources/layouts/Case/detailSmall.json +++ b/application/Espo/Modules/Crm/Resources/layouts/Case/detailSmall.json @@ -1,14 +1,12 @@ [ { - "label":"", "rows":[ - [{"name":"name", "fullWidth": true}], - [{"name":"status"}, {"name":"priority"}], - [{"name":"type"}, {"name":"number"}], - [{"name":"account", "fullWidth": true}], - [{"name":"contacts", "fullWidth": true}], - [{"name":"description", "fullWidth": true}], - [{"name":"attachments", "fullWidth": true}] + [{"name": "name"}], + [{"name": "status"}, {"name": "priority"}], + [{"name": "type"}, {"name": "number"}], + [{"name": "account"}, {"name": "contacts"}], + [{"name": "description"}], + [{"name": "attachments"}] ] } -] \ No newline at end of file +] diff --git a/application/Espo/Modules/Crm/Resources/layouts/Meeting/detailSmall.json b/application/Espo/Modules/Crm/Resources/layouts/Meeting/detailSmall.json index 5580b79e04..4976413783 100644 --- a/application/Espo/Modules/Crm/Resources/layouts/Meeting/detailSmall.json +++ b/application/Espo/Modules/Crm/Resources/layouts/Meeting/detailSmall.json @@ -1,15 +1,14 @@ [ { - "label":"", "rows":[ - [{"name":"name", "fullWidth": true}], - [{"name":"status", "fullWidth": true}], - [{"name":"dateStart", "fullWidth": true}], - [{"name":"duration", "fullWidth": true}], - [{"name":"dateEnd", "fullWidth": true}], - [{"name":"parent", "fullWidth": true}], - [{"name":"reminders", "fullWidth": true}], - [{"name":"description", "fullWidth": true}] + [{"name":"name"}], + [{"name":"status"}, false], + [{"name":"dateStart"}], + [{"name":"duration"}, false], + [{"name":"dateEnd"}], + [{"name":"parent"}], + [{"name":"reminders"}], + [{"name":"description"}] ] } -] \ No newline at end of file +] diff --git a/application/Espo/Repositories/Email.php b/application/Espo/Repositories/Email.php index 86b76d52d5..22790534ee 100644 --- a/application/Espo/Repositories/Email.php +++ b/application/Espo/Repositories/Email.php @@ -186,13 +186,21 @@ class Email extends Database implements return; } + $setFetched = !$entity->isAttributeChanged($type . 'EmailAddressesNames'); + $addresses = []; foreach (get_object_vars($names) as $address) { $addresses[] = $address; } - $entity->set($type, implode(';', $addresses)); + $value = implode(';', $addresses); + + $entity->set($type, $value); + + if ($setFetched) { + $entity->setFetched($type, $value); + } } /** @@ -289,6 +297,10 @@ class Email extends Database implements $entity->set('nameHash', $nameHash); $entity->set('typeHash', $typeHash); $entity->set('idHash', $idHash); + + $entity->setFetched('nameHash', $nameHash); + $entity->setFetched('typeHash', $typeHash); + $entity->setFetched('idHash', $idHash); } /** diff --git a/application/Espo/Resources/metadata/authenticationMethods/LDAP.json b/application/Espo/Resources/metadata/authenticationMethods/LDAP.json index 1fff0d57f2..8d9f7d55b8 100644 --- a/application/Espo/Resources/metadata/authenticationMethods/LDAP.json +++ b/application/Espo/Resources/metadata/authenticationMethods/LDAP.json @@ -89,6 +89,10 @@ { "type": "isTrue", "attribute": "ldapAuth" + }, { + "type": "equals", + "attribute": "authenticationMethod", + "value": "LDAP" } ] } diff --git a/application/Espo/Resources/metadata/entityDefs/EmailTemplate.json b/application/Espo/Resources/metadata/entityDefs/EmailTemplate.json index 1d7f23c710..72da08fa3f 100644 --- a/application/Espo/Resources/metadata/entityDefs/EmailTemplate.json +++ b/application/Espo/Resources/metadata/entityDefs/EmailTemplate.json @@ -2,21 +2,25 @@ "fields": { "name": { "type": "varchar", - "required": true + "required": true, + "audited": true }, "subject": { - "type": "varchar" + "type": "varchar", + "audited": true }, "body": { "type": "wysiwyg", "view": "views/email-template/fields/body", "useIframe": true, - "attachmentField": "attachments" + "attachmentField": "attachments", + "audited": true }, "isHtml": { "type": "bool", "default": true, - "inlineEditDisabled": true + "inlineEditDisabled": true, + "audited": true }, "status": { "type": "enum", @@ -28,7 +32,8 @@ "style": { "Inactive": "info" }, - "maxLength": 8 + "maxLength": 8, + "audited": true }, "oneOff": { "type": "bool", @@ -36,7 +41,8 @@ "tooltip": true }, "attachments": { - "type": "attachmentMultiple" + "type": "attachmentMultiple", + "audited": true }, "category": { "type": "link", @@ -47,7 +53,8 @@ "view": "views/fields/assigned-user" }, "teams": { - "type": "linkMultiple" + "type": "linkMultiple", + "audited": true }, "createdAt": { "type": "datetime", diff --git a/application/Espo/Resources/metadata/themes/Hazyblue.json b/application/Espo/Resources/metadata/themes/Hazyblue.json index d091b062b6..34a3c2c910 100644 --- a/application/Espo/Resources/metadata/themes/Hazyblue.json +++ b/application/Espo/Resources/metadata/themes/Hazyblue.json @@ -1,7 +1,7 @@ { "stylesheet": "client/css/espo/hazyblue.css", "stylesheetIframe": "client/css/espo/hazyblue-iframe.css", - "logo": "client/img/logo-hazy.svg", + "logo": "client/img/logo-light.svg", "textColor": "#333", "chartGridColor": "#ddd", "chartTickColor": "#e8eced", diff --git a/client/img/logo-hazy.svg b/client/img/logo-hazy.svg deleted file mode 100644 index fcd844f57a..0000000000 --- a/client/img/logo-hazy.svg +++ /dev/null @@ -1,17 +0,0 @@ - - diff --git a/client/modules/crm/src/views/knowledge-base-article/record/detail-quick.js b/client/modules/crm/src/views/knowledge-base-article/record/detail-quick.js index df638c927b..2bca91c0fc 100644 --- a/client/modules/crm/src/views/knowledge-base-article/record/detail-quick.js +++ b/client/modules/crm/src/views/knowledge-base-article/record/detail-quick.js @@ -26,12 +26,8 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -define('crm:views/knowledge-base-article/record/detail-quick', ['views/record/detail-small'], function (Dep) { +import DetailRecordView from 'views/record/detail'; - return Dep.extend({ - - isWide: true, - sideView: false, - }); -}); +export default class extends DetailRecordView { +} diff --git a/client/modules/crm/src/views/knowledge-base-article/record/edit-quick.js b/client/modules/crm/src/views/knowledge-base-article/record/edit-quick.js index 8839b251fe..fe972aeb2a 100644 --- a/client/modules/crm/src/views/knowledge-base-article/record/edit-quick.js +++ b/client/modules/crm/src/views/knowledge-base-article/record/edit-quick.js @@ -26,11 +26,8 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -define('crm:views/knowledge-base-article/record/edit-quick', ['views/record/edit-small'], function (Dep) { +import EditRecordView from 'views/record/edit'; - return Dep.extend({ +export default class extends EditRecordView { - isWide: true, - sideView: false, - }); -}); +} diff --git a/client/res/templates/modals/change-password.tpl b/client/res/templates/modals/change-password.tpl index dda26bf367..db39a59fcb 100644 --- a/client/res/templates/modals/change-password.tpl +++ b/client/res/templates/modals/change-password.tpl @@ -1,30 +1,40 @@ -