diff --git a/application/Espo/Tools/Stream/RecordService.php b/application/Espo/Tools/Stream/RecordService.php
index 7712764489..9f4af032ad 100644
--- a/application/Espo/Tools/Stream/RecordService.php
+++ b/application/Espo/Tools/Stream/RecordService.php
@@ -424,7 +424,8 @@ class RecordService
{
if (
$note->getType() === Note::TYPE_POST ||
- $note->getType() === Note::TYPE_EMAIL_RECEIVED
+ $note->getType() === Note::TYPE_EMAIL_RECEIVED ||
+ $note->getType() === Note::TYPE_EMAIL_SENT
) {
$note->loadAttachments();
}
diff --git a/application/Espo/Tools/Stream/Service.php b/application/Espo/Tools/Stream/Service.php
index 18431582c5..6cc0f712b1 100644
--- a/application/Espo/Tools/Stream/Service.php
+++ b/application/Espo/Tools/Stream/Service.php
@@ -496,20 +496,18 @@ class Service
$note->setSuperParent($email->getAccount());
}
- $withContent = in_array($entityType, $this->config->get('streamEmailWithContentEntityTypeList', []));
+ $data = [
+ 'emailId' => $email->getId(),
+ 'emailName' => $email->getSubject(),
+ 'isInitial' => $isInitial,
+ 'hasAttachment' => count($email->getAttachmentIdList()) > 0,
+ ];
+
+ $withContent = $this->toStoreEmailContent($entityType);
if ($withContent) {
$note->setPost($email->getBodyPlain());
- }
-
- $data = [];
-
- $data['emailId'] = $email->getId();
- $data['emailName'] = $email->getSubject();
- $data['isInitial'] = $isInitial;
-
- if ($withContent) {
- $data['attachmentsIds'] = $email->get('attachmentsIds');
+ $data['attachmentsIds'] = $email->getAttachmentIdList();
}
$from = $email->getFromAddress();
@@ -532,7 +530,7 @@ class Service
}
}
- $note->setData((object) $data);
+ $note->setData($data);
$this->entityManager->saveEntity($note);
@@ -556,19 +554,17 @@ class Service
$note->setSuperParent($email->getAccount());
}
- $withContent = in_array($entityType, $this->config->get('streamEmailWithContentEntityTypeList', []));
+ $data = [
+ 'emailId' => $email->getId(),
+ 'emailName' => $email->getSubject(),
+ 'hasAttachment' => count($email->getAttachmentIdList()) > 0,
+ ];
+
+ $withContent = $this->toStoreEmailContent($entityType);
if ($withContent) {
$note->setPost($email->getBodyPlain());
- }
-
- $data = [];
-
- $data['emailId'] = $email->getId();
- $data['emailName'] = $email->getSubject();
-
- if ($withContent) {
- $data['attachmentsIds'] = $email->get('attachmentsIds');
+ $data['attachmentsIds'] = $email->getAttachmentIdList();
}
$user = $this->user;
@@ -578,7 +574,7 @@ class Service
if (!$user->isSystem()) {
$person = $user;
} else {
- $from = $email->get('from');
+ $from = $email->getFromAddress();
if ($from) {
$person = $this->getEmailAddressRepository()->getEntityByAddress($from);
@@ -591,7 +587,7 @@ class Service
$data['personEntityId'] = $person->getId();
}
- $note->set('data', (object) $data);
+ $note->setData($data);
$this->entityManager->saveEntity($note);
@@ -1369,4 +1365,9 @@ class Service
$this->entityManager->saveEntity($entity, [SaveOption::SKIP_ALL => true]);
}
+
+ private function toStoreEmailContent(string $entityType): bool
+ {
+ return in_array($entityType, $this->config->get('streamEmailWithContentEntityTypeList', []));
+ }
}
diff --git a/client/res/templates/stream/notes/email-received.tpl b/client/res/templates/stream/notes/email-received.tpl
index 9699417a5d..e48d38bad5 100644
--- a/client/res/templates/stream/notes/email-received.tpl
+++ b/client/res/templates/stream/notes/email-received.tpl
@@ -17,6 +17,11 @@
data-id="{{emailId}}"
data-scope="Email"
>{{{message}}}
+
@@ -28,6 +33,17 @@
>{{emailName}}
+{{#if detailsIsShown}}
+ {{#if bodyField}}
+
+
{{{bodyField}}}
+ {{#if attachmentsField}}
+
{{{attachmentsField}}}
+ {{/if}}
+
+ {{/if}}
+{{/if}}
+
{{#if hasPost}}
{{{post}}}
@@ -46,4 +62,3 @@
{{/if}}
-
diff --git a/client/res/templates/stream/notes/email-sent.tpl b/client/res/templates/stream/notes/email-sent.tpl
index ae8392ff9f..2c78f1e78c 100644
--- a/client/res/templates/stream/notes/email-sent.tpl
+++ b/client/res/templates/stream/notes/email-sent.tpl
@@ -17,6 +17,11 @@
data-id="{{emailId}}"
data-scope="Email"
>{{{message}}}
+
@@ -28,6 +33,17 @@
>{{emailName}}
+{{#if detailsIsShown}}
+ {{#if bodyField}}
+
+
{{{bodyField}}}
+ {{#if attachmentsField}}
+
{{{attachmentsField}}}
+ {{/if}}
+
+ {{/if}}
+{{/if}}
+
{{#if hasPost}}
{{{post}}}
diff --git a/client/src/views/email/fields/body.js b/client/src/views/email/fields/body.js
index 1ece9f87b5..54a12b442d 100644
--- a/client/src/views/email/fields/body.js
+++ b/client/src/views/email/fields/body.js
@@ -90,6 +90,10 @@ class EmailBodyFieldView extends WysiwygFieldView {
afterRender() {
super.afterRender();
+ if (!this.element) {
+ return;
+ }
+
this.controlInsertFieldButton();
if (this.isReadMode() && this.replyPart) {
diff --git a/client/src/views/stream/notes/email-received.js b/client/src/views/stream/notes/email-received.js
index 0e1fd2cb05..601f8e61aa 100644
--- a/client/src/views/stream/notes/email-received.js
+++ b/client/src/views/stream/notes/email-received.js
@@ -27,28 +27,68 @@
************************************************************************/
import NoteStreamView from 'views/stream/note';
+import EmailBodyFieldView from 'views/email/fields/body';
+import AttachmentMultipleFieldView from 'views/fields/attachment-multiple';
class EmailReceivedNoteStreamView extends NoteStreamView {
template = 'stream/notes/email-received'
isRemovable = false
isSystemAvatar = true
+ detailsIsShown = false
+
+ /**
+ * @private
+ * @type {import('views/fields/base').default}
+ */
+ bodyFieldView
+
+ /**
+ * @private
+ * @type {import('views/fields/attachment-multiple').default}
+ */
+ attachmentsFieldView
+
+ /**
+ * @private
+ * @type {import('model').default}
+ */
+ formModel
+
+ /**
+ * @private
+ * @type {string}
+ */
+ emailId
data() {
return {
...super.data(),
emailId: this.emailId,
emailName: this.emailName,
- hasPost: this.hasPost,
+ hasPost: this.hasPost && !this.detailsIsShown,
hasAttachments: this.hasAttachments,
emailIconClassName: this.getMetadata().get(['clientDefs', 'Email', 'iconClass']) || '',
isPinned: this.isThis && this.model.get('isPinned') && this.model.collection &&
!this.model.collection.pinnedList,
+ detailsIsShown: this.detailsIsShown,
};
}
setup() {
- const data = /** @type {Record} */this.model.get('data') || {};
+ this.addActionHandler('expandDetails', () => this.toggleDetails());
+
+ const data =
+ /**
+ * @type {{
+ * emailId: string,
+ * emailName: string,
+ * personEntityType?: string,
+ * personEntityId?: string,
+ * personEntityName?: string,
+ * isInitial?: boolean,
+ * }} */
+ this.model.get('data') || {};
this.emailId = data.emailId;
this.emailName = data.emailName;
@@ -118,6 +158,70 @@ class EmailReceivedNoteStreamView extends NoteStreamView {
this.createMessage();
}
+
+ /**
+ * @private
+ * Warning: The same method exists in email-sent.
+ */
+ async toggleDetails() {
+ this.detailsIsShown = !this.detailsIsShown;
+
+ if (!this.detailsIsShown && this.formModel) {
+ this.formModel.abortLastFetch();
+
+ Espo.Ui.notify();
+ }
+
+ await this.reRender();
+
+ if (!this.detailsIsShown || !this.emailId) {
+ return;
+ }
+
+ if (this.bodyFieldView) {
+ this.bodyFieldView.toShowQuotePart = false;
+
+ await this.bodyFieldView.reRender();
+
+ return;
+ }
+
+ this.formModel = await this.getModelFactory().create('Email');
+
+ this.formModel.id = this.emailId;
+
+ Espo.Ui.notify(' ... ');
+
+ await this.formModel.fetch();
+
+ this.bodyFieldView = new EmailBodyFieldView({
+ name: 'body',
+ model: this.formModel,
+ mode: 'detail',
+ readOnly: true,
+ });
+
+ await this.assignView('bodyField', this.bodyFieldView, '[data-name="body"]');
+
+ if (
+ !this.hasAttachments &&
+ this.formModel.attributes.attachmentsIds &&
+ this.formModel.attributes.attachmentsIds.length
+ ) {
+ this.attachmentsFieldView = new AttachmentMultipleFieldView({
+ name: 'attachments',
+ model: this.formModel,
+ mode: 'detail',
+ readOnly: true,
+ });
+
+ await this.assignView('attachmentsField', this.attachmentsFieldView, '[data-name="attachments"]');
+ }
+
+ Espo.Ui.notify();
+
+ await this.reRender();
+ }
}
export default EmailReceivedNoteStreamView;
diff --git a/client/src/views/stream/notes/email-sent.js b/client/src/views/stream/notes/email-sent.js
index 25cf5e92bc..d7926cb64b 100644
--- a/client/src/views/stream/notes/email-sent.js
+++ b/client/src/views/stream/notes/email-sent.js
@@ -27,27 +27,66 @@
************************************************************************/
import NoteStreamView from 'views/stream/note';
+import EmailBodyFieldView from 'views/email/fields/body';
+import AttachmentMultipleFieldView from 'views/fields/attachment-multiple';
class EmailSentNoteStreamView extends NoteStreamView {
template = 'stream/notes/email-sent'
isRemovable = false
+ /**
+ * @private
+ * @type {import('views/fields/base').default}
+ */
+ bodyFieldView
+
+ /**
+ * @private
+ * @type {import('views/fields/attachment-multiple').default}
+ */
+ attachmentsFieldView
+
+ /**
+ * @private
+ * @type {import('model').default}
+ */
+ formModel
+
+ /**
+ * @private
+ * @type {string}
+ */
+ emailId
+
data() {
return {
...super.data(),
emailId: this.emailId,
emailName: this.emailName,
- hasPost: this.hasPost,
+ hasPost: this.hasPost && !this.detailsIsShown,
hasAttachments: this.hasAttachments,
emailIconClassName: this.getMetadata().get(['clientDefs', 'Email', 'iconClass']) || '',
isPinned: this.isThis && this.model.get('isPinned') && this.model.collection &&
!this.model.collection.pinnedList,
+ detailsIsShown: this.detailsIsShown,
};
}
setup() {
- const data = /** @type {Record} */this.model.get('data') || {};
+ this.addActionHandler('expandDetails', () => this.toggleDetails());
+
+ const data =
+ /**
+ * @type {{
+ * emailId: string,
+ * emailName: string,
+ * personEntityType?: string,
+ * personEntityId?: string,
+ * personEntityName?: string,
+ * isInitial?: boolean,
+ * }} */
+ this.model.get('data') || {};
this.emailId = data.emailId;
this.emailName = data.emailName;
@@ -102,6 +141,70 @@ class EmailSentNoteStreamView extends NoteStreamView {
this.createMessage();
}
+
+ /**
+ * @private
+ * Warning: The same method exists in email-received.
+ */
+ async toggleDetails() {
+ this.detailsIsShown = !this.detailsIsShown;
+
+ if (!this.detailsIsShown && this.formModel) {
+ this.formModel.abortLastFetch();
+
+ Espo.Ui.notify();
+ }
+
+ await this.reRender();
+
+ if (!this.detailsIsShown || !this.emailId) {
+ return;
+ }
+
+ if (this.bodyFieldView) {
+ this.bodyFieldView.toShowQuotePart = false;
+
+ await this.bodyFieldView.reRender();
+
+ return;
+ }
+
+ this.formModel = await this.getModelFactory().create('Email');
+
+ this.formModel.id = this.emailId;
+
+ Espo.Ui.notify(' ... ');
+
+ await this.formModel.fetch();
+
+ this.bodyFieldView = new EmailBodyFieldView({
+ name: 'body',
+ model: this.formModel,
+ mode: 'detail',
+ readOnly: true,
+ });
+
+ await this.assignView('bodyField', this.bodyFieldView, '[data-name="body"]');
+
+ if (
+ !this.hasAttachments &&
+ this.formModel.attributes.attachmentsIds &&
+ this.formModel.attributes.attachmentsIds.length
+ ) {
+ this.attachmentsFieldView = new AttachmentMultipleFieldView({
+ name: 'attachments',
+ model: this.formModel,
+ mode: 'detail',
+ readOnly: true,
+ });
+
+ await this.assignView('attachmentsField', this.attachmentsFieldView, '[data-name="attachments"]');
+ }
+
+ Espo.Ui.notify();
+
+ await this.reRender();
+ }
}
export default EmailSentNoteStreamView;