emails archive
This commit is contained in:
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 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\Classes\FieldProcessing\Email;
|
||||
|
||||
use Espo\Core\FieldProcessing\Loader;
|
||||
use Espo\Core\FieldProcessing\Loader\Params;
|
||||
use Espo\Entities\Email;
|
||||
use Espo\Entities\EmailFolder;
|
||||
use Espo\ORM\Entity;
|
||||
use Espo\ORM\EntityManager;
|
||||
|
||||
/**
|
||||
* @implements Loader<Email>
|
||||
*/
|
||||
class FolderDataLoader implements Loader
|
||||
{
|
||||
public function __construct(private EntityManager $entityManager) {}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
$folderId = $entity->get(Email::USERS_COLUMN_FOLDER_ID);
|
||||
|
||||
if (!$folderId) {
|
||||
return;
|
||||
}
|
||||
|
||||
$folder = $this->entityManager
|
||||
->getRDBRepositoryByClass(EmailFolder::class)
|
||||
->select(['id', 'name'])
|
||||
->where(['id' => $folderId])
|
||||
->findOne();
|
||||
|
||||
if (!$folder) {
|
||||
return;
|
||||
}
|
||||
|
||||
$entity->set('folderName', $folder->getName());
|
||||
}
|
||||
}
|
||||
@@ -41,14 +41,10 @@ use Espo\Entities\User;
|
||||
*/
|
||||
class UserColumnsLoader implements Loader
|
||||
{
|
||||
private EntityManager $entityManager;
|
||||
private User $user;
|
||||
|
||||
public function __construct(EntityManager $entityManager, User $user)
|
||||
{
|
||||
$this->entityManager = $entityManager;
|
||||
$this->user = $user;
|
||||
}
|
||||
public function __construct(
|
||||
private EntityManager $entityManager,
|
||||
private User $user
|
||||
) {}
|
||||
|
||||
public function process(Entity $entity, Params $params): void
|
||||
{
|
||||
@@ -58,6 +54,7 @@ class UserColumnsLoader implements Loader
|
||||
Email::USERS_COLUMN_IS_READ,
|
||||
Email::USERS_COLUMN_IS_IMPORTANT,
|
||||
Email::USERS_COLUMN_IN_TRASH,
|
||||
Email::USERS_COLUMN_IN_ARCHIVE,
|
||||
])
|
||||
->where([
|
||||
'deleted' => false,
|
||||
@@ -70,6 +67,7 @@ class UserColumnsLoader implements Loader
|
||||
$entity->set(Email::USERS_COLUMN_IS_READ, null);
|
||||
$entity->clear(Email::USERS_COLUMN_IS_IMPORTANT);
|
||||
$entity->clear(Email::USERS_COLUMN_IN_TRASH);
|
||||
$entity->clear(Email::USERS_COLUMN_IN_ARCHIVE);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -78,6 +76,8 @@ class UserColumnsLoader implements Loader
|
||||
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(),
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,11 @@ class MoveToFolder implements MassAction
|
||||
throw new BadRequest("No folder ID.");
|
||||
}
|
||||
|
||||
if ($folderId !== Folder::INBOX && !str_starts_with($folderId, 'group:')) {
|
||||
if (
|
||||
$folderId !== Folder::INBOX &&
|
||||
$folderId !== Folder::ARCHIVE &&
|
||||
!str_starts_with($folderId, 'group:')
|
||||
) {
|
||||
$folder = $this->entityManager
|
||||
->getRDBRepositoryByClass(EmailFolder::class)
|
||||
->where([
|
||||
|
||||
@@ -93,6 +93,7 @@ class Main implements AdditionalApplier
|
||||
Email::USERS_COLUMN_IS_READ,
|
||||
Email::USERS_COLUMN_IS_IMPORTANT,
|
||||
Email::USERS_COLUMN_IN_TRASH,
|
||||
Email::USERS_COLUMN_IN_ARCHIVE,
|
||||
Email::USERS_COLUMN_FOLDER_ID,
|
||||
];
|
||||
|
||||
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 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\Classes\Select\Email\Where\ItemConverters;
|
||||
|
||||
use Espo\Core\Select\Where\Item;
|
||||
use Espo\Core\Select\Where\ItemConverter;
|
||||
use Espo\Classes\Select\Email\Helpers\JoinHelper;
|
||||
use Espo\Entities\Email;
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Query\Part\WhereClause;
|
||||
use Espo\ORM\Query\Part\WhereItem as WhereClauseItem;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
|
||||
class InArchiveIsFalse implements ItemConverter
|
||||
{
|
||||
public function __construct(private User $user, private JoinHelper $joinHelper)
|
||||
{}
|
||||
|
||||
public function convert(QueryBuilder $queryBuilder, Item $item): WhereClauseItem
|
||||
{
|
||||
$this->joinHelper->joinEmailUser($queryBuilder, $this->user->getId());
|
||||
|
||||
return WhereClause::fromRaw([
|
||||
Email::ALIAS_INBOX . '.inArchive' => false,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
<?php
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 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\Classes\Select\Email\Where\ItemConverters;
|
||||
|
||||
use Espo\Core\Select\Where\Item;
|
||||
use Espo\Core\Select\Where\ItemConverter;
|
||||
use Espo\Classes\Select\Email\Helpers\JoinHelper;
|
||||
use Espo\Entities\Email;
|
||||
use Espo\Entities\User;
|
||||
use Espo\ORM\Query\Part\WhereClause;
|
||||
use Espo\ORM\Query\Part\WhereItem as WhereClauseItem;
|
||||
use Espo\ORM\Query\SelectBuilder as QueryBuilder;
|
||||
|
||||
class InArchiveIsTrue implements ItemConverter
|
||||
{
|
||||
public function __construct(private User $user, private JoinHelper $joinHelper)
|
||||
{}
|
||||
|
||||
public function convert(QueryBuilder $queryBuilder, Item $item): WhereClauseItem
|
||||
{
|
||||
$this->joinHelper->joinEmailUser($queryBuilder, $this->user->getId());
|
||||
|
||||
return WhereClause::fromRaw([
|
||||
Email::ALIAS_INBOX . '.inArchive' => true,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,9 @@ use Espo\Entities\User;
|
||||
use Espo\Classes\Select\Email\Helpers\JoinHelper;
|
||||
use Espo\Tools\Email\Folder;
|
||||
|
||||
/**
|
||||
* @noinspection PhpUnused
|
||||
*/
|
||||
class InFolder implements ItemConverter
|
||||
{
|
||||
public function __construct(
|
||||
@@ -59,17 +62,19 @@ class InFolder implements ItemConverter
|
||||
Folder::IMPORTANT => $this->convertImportant($queryBuilder),
|
||||
Folder::SENT => $this->convertSent($queryBuilder),
|
||||
Folder::TRASH => $this->convertTrash($queryBuilder),
|
||||
Folder::DRAFTS => $this->convertDraft($queryBuilder),
|
||||
Folder::ARCHIVE => $this->convertArchive($queryBuilder),
|
||||
Folder::DRAFTS => $this->convertDraft(),
|
||||
default => $this->convertFolderId($queryBuilder, $folderId),
|
||||
};
|
||||
}
|
||||
|
||||
protected function convertInbox(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
private function convertInbox(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
{
|
||||
$this->joinEmailUser($queryBuilder);
|
||||
|
||||
$whereClause = [
|
||||
Email::ALIAS_INBOX . '.inTrash' => false,
|
||||
Email::ALIAS_INBOX . '.inArchive' => false,
|
||||
Email::ALIAS_INBOX . '.folderId' => null,
|
||||
Email::ALIAS_INBOX . '.userId' => $this->user->getId(),
|
||||
[
|
||||
@@ -83,7 +88,7 @@ class InFolder implements ItemConverter
|
||||
|
||||
$emailAddressIdList = $this->getEmailAddressIdList();
|
||||
|
||||
if (!empty($emailAddressIdList)) {
|
||||
if ($emailAddressIdList !== []) {
|
||||
$whereClause['fromEmailAddressId!='] = $emailAddressIdList;
|
||||
|
||||
$whereClause[] = [
|
||||
@@ -92,8 +97,7 @@ class InFolder implements ItemConverter
|
||||
'createdById!=' => $this->user->getId(),
|
||||
],
|
||||
];
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
$whereClause[] = [
|
||||
'status' => Email::STATUS_ARCHIVED,
|
||||
'createdById!=' => $this->user->getId(),
|
||||
@@ -103,7 +107,7 @@ class InFolder implements ItemConverter
|
||||
return WhereClause::fromRaw($whereClause);
|
||||
}
|
||||
|
||||
protected function convertSent(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
private function convertSent(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
{
|
||||
$this->joinEmailUser($queryBuilder);
|
||||
|
||||
@@ -122,7 +126,7 @@ class InFolder implements ItemConverter
|
||||
]);
|
||||
}
|
||||
|
||||
protected function convertImportant(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
private function convertImportant(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
{
|
||||
$this->joinEmailUser($queryBuilder);
|
||||
|
||||
@@ -132,7 +136,7 @@ class InFolder implements ItemConverter
|
||||
]);
|
||||
}
|
||||
|
||||
protected function convertTrash(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
private function convertTrash(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
{
|
||||
$this->joinEmailUser($queryBuilder);
|
||||
|
||||
@@ -142,7 +146,17 @@ class InFolder implements ItemConverter
|
||||
]);
|
||||
}
|
||||
|
||||
protected function convertDraft(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
private function convertArchive(QueryBuilder $queryBuilder): WhereClauseItem
|
||||
{
|
||||
$this->joinEmailUser($queryBuilder);
|
||||
|
||||
return WhereClause::fromRaw([
|
||||
Email::ALIAS_INBOX . '.userId' => $this->user->getId(),
|
||||
Email::ALIAS_INBOX . '.inArchive' => true,
|
||||
]);
|
||||
}
|
||||
|
||||
private function convertDraft(): WhereClauseItem
|
||||
{
|
||||
return WhereClause::fromRaw([
|
||||
'status' => Email::STATUS_DRAFT,
|
||||
@@ -150,7 +164,7 @@ class InFolder implements ItemConverter
|
||||
]);
|
||||
}
|
||||
|
||||
protected function convertFolderId(QueryBuilder $queryBuilder, string $folderId): WhereClauseItem
|
||||
private function convertFolderId(QueryBuilder $queryBuilder, string $folderId): WhereClauseItem
|
||||
{
|
||||
$this->joinEmailUser($queryBuilder);
|
||||
|
||||
@@ -166,12 +180,14 @@ class InFolder implements ItemConverter
|
||||
'OR' => [
|
||||
Email::ALIAS_INBOX . '.id' => null,
|
||||
Email::ALIAS_INBOX . '.inTrash' => false,
|
||||
Email::ALIAS_INBOX . '.inArchive' => false,
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
return WhereClause::fromRaw([
|
||||
Email::ALIAS_INBOX . '.inTrash' => false,
|
||||
Email::ALIAS_INBOX . '.inArchive' => false,
|
||||
Email::ALIAS_INBOX . '.folderId' => $folderId,
|
||||
'groupFolderId' => null,
|
||||
]);
|
||||
|
||||
@@ -55,6 +55,7 @@ class Email extends Entity
|
||||
|
||||
public const USERS_COLUMN_IS_READ = 'isRead';
|
||||
public const USERS_COLUMN_IN_TRASH = 'inTrash';
|
||||
public const USERS_COLUMN_IN_ARCHIVE = 'inArchive';
|
||||
public const USERS_COLUMN_FOLDER_ID = 'folderId';
|
||||
public const USERS_COLUMN_IS_IMPORTANT = 'isImportant';
|
||||
|
||||
|
||||
@@ -29,8 +29,15 @@
|
||||
|
||||
namespace Espo\Entities;
|
||||
|
||||
class EmailFolder extends \Espo\Core\ORM\Entity
|
||||
use Espo\Core\ORM\Entity;
|
||||
|
||||
class EmailFolder extends Entity
|
||||
{
|
||||
public const ENTITY_TYPE = 'EmailFolder';
|
||||
|
||||
public function getName(): string
|
||||
{
|
||||
return $this->get('name') ?? '';
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,9 @@
|
||||
"isReplied": "Is Replied",
|
||||
"isNotReplied": "Is Not Replied",
|
||||
"isUsers": "Is User's",
|
||||
"isUsersSent": "Is User's Sent",
|
||||
"inTrash": "In Trash",
|
||||
"inArchive": "In Archive",
|
||||
"folder": "Folder",
|
||||
"inboundEmails": "Group Accounts",
|
||||
"emailAccounts": "Personal Accounts",
|
||||
@@ -44,6 +46,7 @@
|
||||
"messageId": "Message Id",
|
||||
"messageIdInternal": "Message Id (Internal)",
|
||||
"folderId": "Folder Id",
|
||||
"folderString": "Folder",
|
||||
"fromName": "From Name",
|
||||
"fromString": "From String",
|
||||
"fromAddress": "From Address",
|
||||
@@ -79,7 +82,7 @@
|
||||
"Draft": "Draft",
|
||||
"Sending": "Sending",
|
||||
"Sent": "Sent",
|
||||
"Archived": "Archived",
|
||||
"Archived": "Imported",
|
||||
"Received": "Received",
|
||||
"Failed": "Failed"
|
||||
}
|
||||
@@ -111,7 +114,7 @@
|
||||
"Move to Trash": "Move to Trash",
|
||||
"Retrieve from Trash": "Retrieve from Trash",
|
||||
"Move to Folder": "Move to Folder",
|
||||
"Moving to folder": "Moving to Folder",
|
||||
"Moved to Archive": "Moved to Archive",
|
||||
"Filters": "Filters",
|
||||
"Folders": "Folders",
|
||||
"Group Folders": "Group Folders",
|
||||
@@ -141,12 +144,16 @@
|
||||
},
|
||||
"presetFilters": {
|
||||
"sent": "Sent",
|
||||
"archived": "Archived",
|
||||
"archived": "Imported",
|
||||
"inbox": "Inbox",
|
||||
"drafts": "Drafts",
|
||||
"trash": "Trash",
|
||||
"archive": "Archive",
|
||||
"important": "Important"
|
||||
},
|
||||
"actions": {
|
||||
"moveToArchive": "Archive"
|
||||
},
|
||||
"massActions": {
|
||||
"markAsRead": "Mark as Read",
|
||||
"markAsNotRead": "Mark as Not Read",
|
||||
@@ -154,6 +161,7 @@
|
||||
"markAsNotImportant": "Unmark Importance",
|
||||
"moveToTrash": "Move to Trash",
|
||||
"moveToFolder": "Move to Folder",
|
||||
"moveToArchive": "Archive",
|
||||
"retrieveFromTrash": "Retrieve from Trash"
|
||||
},
|
||||
"otherFields": {
|
||||
|
||||
@@ -5,6 +5,9 @@
|
||||
{
|
||||
"name": "status"
|
||||
},
|
||||
{
|
||||
"name": "folderString"
|
||||
},
|
||||
{
|
||||
"name": "replied"
|
||||
},
|
||||
|
||||
@@ -144,6 +144,20 @@
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"folderString": {
|
||||
"visible": {
|
||||
"conditionGroup": [
|
||||
{
|
||||
"type": "isTrue",
|
||||
"attribute": "isUsers"
|
||||
},
|
||||
{
|
||||
"type": "isFalse",
|
||||
"attribute": "isUsersSent"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"panels": {
|
||||
|
||||
@@ -198,6 +198,13 @@
|
||||
"customizationDisabled": true,
|
||||
"layoutMassUpdateDisabled": true
|
||||
},
|
||||
"inArchive": {
|
||||
"type": "bool",
|
||||
"notStorable": true,
|
||||
"default": false,
|
||||
"customizationDisabled": true,
|
||||
"layoutMassUpdateDisabled": true
|
||||
},
|
||||
"folderId": {
|
||||
"type": "varchar",
|
||||
"notStorable": true,
|
||||
@@ -213,13 +220,32 @@
|
||||
"customizationDisabled": true,
|
||||
"layoutMassUpdateDisabled": true
|
||||
},
|
||||
"isUsersSent": {
|
||||
"type": "bool",
|
||||
"notStorable": true,
|
||||
"readOnly": true,
|
||||
"utility": true
|
||||
},
|
||||
"folder": {
|
||||
"type": "link",
|
||||
"notStorable": true,
|
||||
"orderDisabled": true,
|
||||
"readOnly": true,
|
||||
"entity": "EmailFolder",
|
||||
"customizationDisabled": true
|
||||
"customizationDisabled": true,
|
||||
"layoutAvailabilityList": []
|
||||
},
|
||||
"folderString": {
|
||||
"type": "link",
|
||||
"notStorable": true,
|
||||
"orderDisabled": true,
|
||||
"readOnly": true,
|
||||
"entity": "EmailFolder",
|
||||
"customizationDisabled": true,
|
||||
"view": "views/email/fields/folder-string",
|
||||
"layoutAvailabilityList": [
|
||||
"defaultSidePanel"
|
||||
]
|
||||
},
|
||||
"nameHash": {
|
||||
"type": "text",
|
||||
@@ -320,7 +346,8 @@
|
||||
"tooltipText"
|
||||
],
|
||||
"inlineEditDisabled": true,
|
||||
"layoutMassUpdateDisabled": true
|
||||
"layoutMassUpdateDisabled": true,
|
||||
"layoutDefaultSidePanelDisabled": true
|
||||
},
|
||||
"status": {
|
||||
"type": "enum",
|
||||
@@ -585,6 +612,10 @@
|
||||
"type": "bool",
|
||||
"default": false
|
||||
},
|
||||
"inArchive": {
|
||||
"type": "bool",
|
||||
"default": false
|
||||
},
|
||||
"folderId": {
|
||||
"type": "foreignId",
|
||||
"default": null
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
"readLoaderClassNameList": [
|
||||
"Espo\\Classes\\FieldProcessing\\Email\\AddressDataLoader",
|
||||
"Espo\\Classes\\FieldProcessing\\Email\\UserColumnsLoader",
|
||||
"Espo\\Classes\\FieldProcessing\\Email\\FolderDataLoader",
|
||||
"Espo\\Classes\\FieldProcessing\\Email\\IcsDataLoader"
|
||||
],
|
||||
"listLoaderClassNameList": [
|
||||
|
||||
@@ -13,6 +13,8 @@
|
||||
"isRead_isFalse": "Espo\\Classes\\Select\\Email\\Where\\ItemConverters\\IsNotReadIsTrue",
|
||||
"inTrash_isTrue": "Espo\\Classes\\Select\\Email\\Where\\ItemConverters\\InTrashIsFalse",
|
||||
"inTrash_isFalse": "Espo\\Classes\\Select\\Email\\Where\\ItemConverters\\InTrashIsTrue",
|
||||
"inArchive_isTrue": "Espo\\Classes\\Select\\Email\\Where\\ItemConverters\\InArchiveIsFalse",
|
||||
"inArchive_isFalse": "Espo\\Classes\\Select\\Email\\Where\\ItemConverters\\InArchiveIsTrue",
|
||||
"isImportant_isTrue": "Espo\\Classes\\Select\\Email\\Where\\ItemConverters\\IsImportantIsTrue",
|
||||
"isImportant_isFalse": "Espo\\Classes\\Select\\Email\\Where\\ItemConverters\\IsImportantIsFalse"
|
||||
},
|
||||
|
||||
@@ -36,5 +36,6 @@ class Folder
|
||||
public const SENT = 'sent';
|
||||
public const DRAFTS = 'drafts';
|
||||
public const IMPORTANT = 'important';
|
||||
public const ARCHIVE = 'archive';
|
||||
public const TRASH = 'trash';
|
||||
}
|
||||
|
||||
@@ -100,17 +100,7 @@ class InboxService
|
||||
$previousFolderLink = $email->getGroupFolder();
|
||||
|
||||
if ($previousFolderLink) {
|
||||
$previousFolderId = $previousFolderLink->getId();
|
||||
|
||||
$previousFolder = $this->entityManager->getEntityById(GroupEmailFolder::ENTITY_TYPE, $previousFolderId);
|
||||
|
||||
if ($previousFolder && !$this->aclManager->checkEntityRead($user, $previousFolder)) {
|
||||
throw new Forbidden("No access to current group folder.");
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkField($user, Email::ENTITY_TYPE, 'groupFolder', Table::ACTION_EDIT)) {
|
||||
throw new Forbidden("No access to `groupFolder` field.");
|
||||
}
|
||||
$this->checkCurrentGroupFolder($previousFolderLink->getId(), $user);
|
||||
}
|
||||
|
||||
if ($folderId && str_starts_with($folderId, 'group:')) {
|
||||
@@ -118,7 +108,7 @@ class InboxService
|
||||
$this->moveToGroupFolder($email, substr($folderId, 6), $user);
|
||||
}
|
||||
catch (Exception $e) {
|
||||
$this->log->debug("Move to group folder exception: " . $e->getMessage());
|
||||
$this->log->debug("Could not move email to group folder. " . $e->getMessage());
|
||||
|
||||
throw $e;
|
||||
}
|
||||
@@ -126,8 +116,14 @@ class InboxService
|
||||
return;
|
||||
}
|
||||
|
||||
if ($folderId === Folder::ARCHIVE) {
|
||||
$this->moveToArchive($email, $user);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($previousFolderLink) {
|
||||
$email->set('groupFolderId', null);
|
||||
$email->setGroupFolderId(null);
|
||||
|
||||
if (!$this->aclManager->checkEntityRead($user, $email)) {
|
||||
throw new Forbidden("No read access to email to unset group folder.");
|
||||
@@ -143,6 +139,7 @@ class InboxService
|
||||
->set([
|
||||
'folderId' => $folderId,
|
||||
'inTrash' => false,
|
||||
'inArchive' => false,
|
||||
])
|
||||
->where([
|
||||
'deleted' => false,
|
||||
@@ -178,9 +175,10 @@ class InboxService
|
||||
throw new Forbidden("No access to `groupFolder` field.");
|
||||
}
|
||||
|
||||
$email->set('groupFolderId', $folderId);
|
||||
|
||||
$email->setGroupFolderId($folderId);
|
||||
$this->entityManager->saveEntity($email);
|
||||
|
||||
$this->retrieveFromArchive($email, $user);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -496,4 +494,68 @@ class InboxService
|
||||
|
||||
return $data;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Forbidden
|
||||
*/
|
||||
public function moveToArchive(Email $email, User $user): void
|
||||
{
|
||||
if (!$this->aclManager->checkEntityRead($user, $email)) {
|
||||
throw new Forbidden("No 'read' access");
|
||||
}
|
||||
|
||||
$update = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->update()
|
||||
->in(Email::RELATIONSHIP_EMAIL_USER)
|
||||
->set([
|
||||
'folderId' => null,
|
||||
'inArchive' => true,
|
||||
'inTrash' => false,
|
||||
])
|
||||
->where([
|
||||
'deleted' => false,
|
||||
'userId' => $user->getId(),
|
||||
'emailId' => $email->getId(),
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($update);
|
||||
}
|
||||
|
||||
public function retrieveFromArchive(Email $email, User $user): void
|
||||
{
|
||||
$update = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->update()
|
||||
->in(Email::RELATIONSHIP_EMAIL_USER)
|
||||
->set([
|
||||
'folderId' => null,
|
||||
'inArchive' => false,
|
||||
])
|
||||
->where([
|
||||
'deleted' => false,
|
||||
'userId' => $user->getId(),
|
||||
'emailId' => $email->getId(),
|
||||
])
|
||||
->build();
|
||||
|
||||
$this->entityManager->getQueryExecutor()->execute($update);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Forbidden
|
||||
*/
|
||||
private function checkCurrentGroupFolder(string $folderId, User $user): void
|
||||
{
|
||||
$folder = $this->entityManager->getEntityById(GroupEmailFolder::ENTITY_TYPE, $folderId);
|
||||
|
||||
if ($folder && !$this->aclManager->checkEntityRead($user, $folder)) {
|
||||
throw new Forbidden("No access to current group folder.");
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkField($user, Email::ENTITY_TYPE, 'groupFolder', Table::ACTION_EDIT)) {
|
||||
throw new Forbidden("No access to `groupFolder` field.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,7 @@ class Service
|
||||
/** @var string[] */
|
||||
protected $systemFolderEndList = [
|
||||
Folder::DRAFTS,
|
||||
Folder::ARCHIVE,
|
||||
Folder::TRASH,
|
||||
];
|
||||
|
||||
|
||||
@@ -46,10 +46,10 @@ define('views/email-folder/modals/select-folder', ['views/modal'], function (Dep
|
||||
|
||||
events: {
|
||||
'click a[data-action="selectFolder"]': function (e) {
|
||||
let $target = $(e.currentTarget);
|
||||
const $target = $(e.currentTarget);
|
||||
|
||||
let id = $target.attr('data-id');
|
||||
let name = $target.attr('data-name');
|
||||
const id = $target.attr('data-id');
|
||||
const name = $target.attr('data-name');
|
||||
|
||||
this.trigger('select', id, name);
|
||||
this.close();
|
||||
@@ -75,7 +75,14 @@ define('views/email-folder/modals/select-folder', ['views/modal'], function (Dep
|
||||
|
||||
this.folderDataList = data.list
|
||||
.filter(item => {
|
||||
return ['inbox', 'important', 'sent', 'drafts', 'trash'].indexOf(item.id) === -1;
|
||||
return [
|
||||
'inbox',
|
||||
'important',
|
||||
'sent',
|
||||
'drafts',
|
||||
'trash',
|
||||
'archive',
|
||||
].indexOf(item.id) === -1;
|
||||
})
|
||||
.map(item => {
|
||||
return {
|
||||
@@ -88,7 +95,12 @@ define('views/email-folder/modals/select-folder', ['views/modal'], function (Dep
|
||||
this.folderDataList.unshift({
|
||||
id: 'inbox',
|
||||
name: this.translate('inbox', 'presetFilters', 'Email'),
|
||||
})
|
||||
});
|
||||
|
||||
this.folderDataList.push({
|
||||
id: 'archive',
|
||||
name: this.translate('archive', 'presetFilters', 'Email'),
|
||||
});
|
||||
})
|
||||
);
|
||||
},
|
||||
|
||||
@@ -117,7 +117,11 @@ class EmailDetailView extends DetailView {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!this.model.hasChanged('isImportant') && !this.model.hasChanged('inTrash')) {
|
||||
if (
|
||||
!this.model.hasChanged('isImportant') &&
|
||||
!this.model.hasChanged('inTrash') &&
|
||||
!this.model.hasChanged('inArchive')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -128,6 +132,23 @@ class EmailDetailView extends DetailView {
|
||||
}
|
||||
});
|
||||
|
||||
this.shortcutKeys['Control+Backspace'] = e => {
|
||||
if ($(e.target).hasClass('note-editable')) {
|
||||
return;
|
||||
}
|
||||
|
||||
const recordView = /** @type {module:views/email/record/detail} */ this.getRecordView();
|
||||
|
||||
if (!this.model.get('isUsers') || this.model.get('inArchive')) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
recordView.actionMoveToArchive();
|
||||
};
|
||||
|
||||
this.shortcutKeys['Control+Delete'] = e => {
|
||||
if ($(e.target).hasClass('note-editable')) {
|
||||
return;
|
||||
@@ -541,6 +562,7 @@ class EmailDetailView extends DetailView {
|
||||
|
||||
const isImportant = this.model.get('isImportant');
|
||||
const inTrash = this.model.get('inTrash');
|
||||
const inArchive = this.model.get('inArchive');
|
||||
|
||||
const rootUrl = this.options.rootUrl || this.options.params.rootUrl || '#' + this.scope;
|
||||
|
||||
@@ -560,12 +582,21 @@ class EmailDetailView extends DetailView {
|
||||
.get(0).innerHTML;
|
||||
}
|
||||
|
||||
let styleClass = '';
|
||||
|
||||
if (isImportant) {
|
||||
styleClass = 'text-warning'
|
||||
} else if (inTrash) {
|
||||
styleClass = 'text-muted';
|
||||
} else if (inArchive) {
|
||||
styleClass = 'text-info';
|
||||
}
|
||||
|
||||
return this.buildHeaderHtml([
|
||||
$root,
|
||||
$('<span>')
|
||||
.addClass('font-size-flexible title')
|
||||
.addClass(isImportant ? 'text-warning' : '')
|
||||
.addClass(inTrash ? 'text-muted' : '')
|
||||
.addClass(styleClass)
|
||||
.text(name),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/************************************************************************
|
||||
* This file is part of EspoCRM.
|
||||
*
|
||||
* EspoCRM – Open Source CRM application.
|
||||
* Copyright (C) 2014-2024 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.
|
||||
************************************************************************/
|
||||
|
||||
import BaseFieldView from 'views/fields/base';
|
||||
|
||||
class EmailFolderStringFieldView extends BaseFieldView {
|
||||
|
||||
// language=Handlebars
|
||||
detailTemplateContent = `
|
||||
{{#if valueIsSet}}
|
||||
{{#if value}}
|
||||
{{value}}
|
||||
{{else}}
|
||||
<span class="none-value">{{translate 'None'}}</span>
|
||||
{{/if}}
|
||||
{{else}}
|
||||
<span class="loading-value"></span>
|
||||
{{/if}}
|
||||
`
|
||||
|
||||
// noinspection JSCheckFunctionSignatures
|
||||
data() {
|
||||
if (!this.model.has('folderId')) {
|
||||
return {valueIsSet: false};
|
||||
}
|
||||
|
||||
return {
|
||||
valueIsSet: true,
|
||||
value: this.getFolderString(),
|
||||
}
|
||||
}
|
||||
|
||||
getAttributeList() {
|
||||
return [
|
||||
'folderId',
|
||||
'folderName',
|
||||
'groupFolderId',
|
||||
'groupFolderName',
|
||||
'inArchive',
|
||||
'inTrash',
|
||||
'isUsersSent',
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return {string}
|
||||
*/
|
||||
getFolderString() {
|
||||
if (this.model.get('inTrash')) {
|
||||
return this.translate('trash', 'presetFilters', 'Email');
|
||||
}
|
||||
|
||||
if (this.model.get('isUsersSent')) {
|
||||
return this.translate('sent', 'presetFilters', 'Email');
|
||||
}
|
||||
|
||||
if (this.model.get('inArchive')) {
|
||||
return this.translate('archive', 'presetFilters', 'Email');
|
||||
}
|
||||
|
||||
if (this.model.get('folderName')) {
|
||||
return this.model.get('folderName');
|
||||
}
|
||||
|
||||
if (this.model.get('groupFolderName')) {
|
||||
return this.model.get('groupFolderName');
|
||||
}
|
||||
|
||||
if (this.model.get('isUsers')) {
|
||||
return this.translate('inbox', 'presetFilters', 'Email');
|
||||
}
|
||||
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export default EmailFolderStringFieldView;
|
||||
@@ -26,83 +26,82 @@
|
||||
* these Appropriate Legal Notices must retain the display of the "EspoCRM" word.
|
||||
************************************************************************/
|
||||
|
||||
define('views/email/fields/subject', ['views/fields/varchar'], function (Dep) {
|
||||
import VarcharFieldView from 'views/fields/varchar';
|
||||
|
||||
return Dep.extend({
|
||||
class EmailSubjectFieldView extends VarcharFieldView {
|
||||
|
||||
listLinkTemplate: 'email/fields/subject/list-link',
|
||||
listLinkTemplate = 'email/fields/subject/list-link'
|
||||
|
||||
data: function () {
|
||||
let data = Dep.prototype.data.call(this);
|
||||
data() {
|
||||
const data = super.data();
|
||||
|
||||
data.isRead = (this.model.get('sentById') === this.getUser().id) || this.model.get('isRead');
|
||||
data.isImportant = this.model.has('isImportant') && this.model.get('isImportant');
|
||||
data.hasAttachment = this.model.has('hasAttachment') && this.model.get('hasAttachment');
|
||||
data.isReplied = this.model.has('isReplied') && this.model.get('isReplied');
|
||||
data.inTrash = this.model.has('inTrash') && this.model.get('inTrash');
|
||||
data.isRead = (this.model.get('sentById') === this.getUser().id) || this.model.get('isRead');
|
||||
data.isImportant = this.model.has('isImportant') && this.model.get('isImportant');
|
||||
data.hasAttachment = this.model.has('hasAttachment') && this.model.get('hasAttachment');
|
||||
data.isReplied = this.model.has('isReplied') && this.model.get('isReplied');
|
||||
data.inTrash = this.model.has('inTrash') && this.model.get('inTrash');
|
||||
|
||||
if (!data.isRead && !this.model.has('isRead')) {
|
||||
data.isRead = true;
|
||||
if (!data.isRead && !this.model.has('isRead')) {
|
||||
data.isRead = true;
|
||||
}
|
||||
|
||||
if (!data.isNotEmpty) {
|
||||
if (
|
||||
this.model.get('name') !== null &&
|
||||
this.model.get('name') !== '' &&
|
||||
this.model.has('name')
|
||||
) {
|
||||
data.isNotEmpty = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!data.isNotEmpty) {
|
||||
if (
|
||||
this.model.get('name') !== null &&
|
||||
this.model.get('name') !== '' &&
|
||||
this.model.has('name')
|
||||
) {
|
||||
data.isNotEmpty = true;
|
||||
return data;
|
||||
}
|
||||
|
||||
getValueForDisplay() {
|
||||
return this.model.get('name');
|
||||
}
|
||||
|
||||
getAttributeList() {
|
||||
return ['name', 'subject', 'isRead', 'isImportant', 'hasAttachment', 'inTrash'];
|
||||
}
|
||||
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.events['click [data-action="showAttachments"]'] = e => {
|
||||
e.stopPropagation();
|
||||
|
||||
this.showAttachments();
|
||||
}
|
||||
|
||||
this.listenTo(this.model, 'change', () => {
|
||||
if (this.mode === this.MODE_LIST || this.mode === this.MODE_LIST_LINK) {
|
||||
if (this.model.hasChanged('isRead') || this.model.hasChanged('isImportant')) {
|
||||
this.reRender();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return data;
|
||||
},
|
||||
fetch() {
|
||||
const data = super.fetch();
|
||||
|
||||
getValueForDisplay: function () {
|
||||
return this.model.get('name');
|
||||
},
|
||||
data.name = data.subject;
|
||||
|
||||
getAttributeList: function () {
|
||||
return ['name', 'subject', 'isRead', 'isImportant', 'hasAttachment', 'inTrash'];
|
||||
},
|
||||
return data;
|
||||
}
|
||||
|
||||
setup: function () {
|
||||
Dep.prototype.setup.call(this);
|
||||
showAttachments() {
|
||||
Espo.Ui.notify(' ... ');
|
||||
|
||||
this.events['click [data-action="showAttachments"]'] = e => {
|
||||
e.stopPropagation();
|
||||
this.createView('dialog', 'views/email/modals/attachments', {model: this.model})
|
||||
.then(view => {
|
||||
view.render();
|
||||
|
||||
this.showAttachments();
|
||||
}
|
||||
|
||||
this.listenTo(this.model, 'change', () => {
|
||||
if (this.mode === 'list' || this.mode === 'listLink') {
|
||||
if (this.model.hasChanged('isRead') || this.model.hasChanged('isImportant')) {
|
||||
this.reRender();
|
||||
}
|
||||
}
|
||||
Espo.Ui.notify(false);
|
||||
});
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
afterRender: function () {
|
||||
Dep.prototype.afterRender.call(this);
|
||||
},
|
||||
|
||||
fetch: function () {
|
||||
var data = Dep.prototype.fetch.call(this);
|
||||
data.name = data.subject;
|
||||
return data;
|
||||
},
|
||||
|
||||
showAttachments: function () {
|
||||
Espo.Ui.notify(' ... ');
|
||||
|
||||
this.createView('dialog', 'views/email/modals/attachments', {model: this.model})
|
||||
.then(view => {
|
||||
view.render();
|
||||
|
||||
Espo.Ui.notify(false);
|
||||
});
|
||||
},
|
||||
});
|
||||
});
|
||||
export default EmailSubjectFieldView;
|
||||
|
||||
@@ -51,6 +51,8 @@ class EmailListView extends ListView {
|
||||
FOLDER_DRAFTS = 'drafts'
|
||||
/** @const */
|
||||
FOLDER_TRASH = 'trash'
|
||||
/** @const */
|
||||
FOLDER_ARCHIVE = 'archive'
|
||||
|
||||
noDropFolderIdList = [
|
||||
'sent',
|
||||
@@ -227,7 +229,7 @@ class EmailListView extends ListView {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (folderId === this.FOLDER_TRASH) {
|
||||
if (folderId === this.FOLDER_TRASH || folderId === this.FOLDER_ARCHIVE) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -321,6 +323,17 @@ class EmailListView extends ListView {
|
||||
this.getEmailRecordView().massActionMoveToTrash();
|
||||
};
|
||||
|
||||
this.shortcutKeys['Control+Backspace'] = e => {
|
||||
if (!this.hasSelectedRecords()) {
|
||||
return;
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
|
||||
this.getEmailRecordView().massActionMoveToArchive();
|
||||
};
|
||||
|
||||
this.shortcutKeys['Control+KeyI'] = e => {
|
||||
if (!this.hasSelectedRecords()) {
|
||||
return;
|
||||
@@ -418,6 +431,7 @@ class EmailListView extends ListView {
|
||||
this.FOLDER_INBOX,
|
||||
this.FOLDER_IMPORTANT,
|
||||
this.FOLDER_SENT,
|
||||
this.FOLDER_ARCHIVE,
|
||||
];
|
||||
|
||||
this.getFolderCollection(collection => {
|
||||
@@ -462,7 +476,7 @@ class EmailListView extends ListView {
|
||||
.then(() => Espo.Ui.notify(false));
|
||||
|
||||
if (id !== this.defaultFolderId) {
|
||||
this.getRouter().navigate('#Email/list/folder=' + id);
|
||||
this.getRouter().navigate(`#Email/list/folder=${id}`);
|
||||
} else {
|
||||
this.getRouter().navigate('#Email');
|
||||
}
|
||||
|
||||
@@ -156,6 +156,14 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
groupIndex: 2,
|
||||
});
|
||||
|
||||
this.addDropdownItem({
|
||||
labelTranslation: 'Email.actions.moveToArchive',
|
||||
name: 'moveToArchive',
|
||||
groupIndex: 2,
|
||||
hidden: this.model.get('inArchive'),
|
||||
onClick: () => this.actionMoveToArchive(),
|
||||
});
|
||||
|
||||
this.addDropdownItem({
|
||||
label: 'Move to Folder',
|
||||
name: 'moveToFolder',
|
||||
@@ -196,6 +204,14 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
}
|
||||
});
|
||||
|
||||
this.listenTo(this.model, 'change:inArchive', () => {
|
||||
if (this.model.get('inArchive')) {
|
||||
this.hideActionItem('moveToArchive');
|
||||
} else {
|
||||
this.showActionItem('moveToArchive');
|
||||
}
|
||||
});
|
||||
|
||||
this.handleTasksField();
|
||||
this.listenTo(this.model, 'change:tasksIds', () => this.handleTasksField());
|
||||
|
||||
@@ -312,7 +328,9 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
|
||||
Espo.Ajax.postRequest(`Email/inbox/folders/${folderId}`, {id: this.model.id})
|
||||
.then(() => {
|
||||
if (folderId === 'inbox') {
|
||||
this.model.set('inArchive', folderId === 'archive');
|
||||
|
||||
if (folderId === 'inbox' || folderId === 'archive') {
|
||||
folderId = null;
|
||||
}
|
||||
|
||||
@@ -324,6 +342,21 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
});
|
||||
}
|
||||
|
||||
actionMoveToArchive() {
|
||||
Espo.Ui.notify(' ... ');
|
||||
|
||||
Espo.Ajax.postRequest(`Email/inbox/folders/archive`, {id: this.model.id})
|
||||
.then(() => {
|
||||
this.model.set('inArchive', true);
|
||||
|
||||
Espo.Ui.info(this.translate('Moved to Archive', 'labels', 'Email'));
|
||||
|
||||
if (this.model.collection) {
|
||||
this.model.collection.trigger('moving-to-archive', this.model.id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
actionShowBodyPlain() {
|
||||
this.createView('bodyPlain', 'views/email/modals/body-plain', {
|
||||
|
||||
@@ -35,7 +35,10 @@ class EmailListRecordView extends ListRecordView {
|
||||
|
||||
rowActionsView = 'views/email/record/row-actions/default'
|
||||
|
||||
massActionList = ['remove', 'massUpdate']
|
||||
massActionList = [
|
||||
'remove',
|
||||
'massUpdate',
|
||||
]
|
||||
|
||||
setup() {
|
||||
super.setup();
|
||||
@@ -43,6 +46,7 @@ class EmailListRecordView extends ListRecordView {
|
||||
if (this.collection.url === this.entityType) {
|
||||
this.addMassAction('retrieveFromTrash', false, true);
|
||||
this.addMassAction('moveToFolder', true, true);
|
||||
this.addMassAction('moveToArchive', true, true);
|
||||
this.addMassAction('markAsNotImportant', false, true);
|
||||
this.addMassAction('markAsImportant', false, true);
|
||||
this.addMassAction('markAsNotRead', false, true);
|
||||
@@ -78,6 +82,18 @@ class EmailListRecordView extends ListRecordView {
|
||||
this.removeRecordFromList(id);
|
||||
}
|
||||
});
|
||||
|
||||
this.listenTo(this.collection, 'moving-to-archive', id => {
|
||||
const model = this.collection.get(id);
|
||||
|
||||
if (model) {
|
||||
model.set('inArchive', true);
|
||||
}
|
||||
|
||||
if (this.collection.selectedFolderId !== 'archive') {
|
||||
this.removeRecordFromList(id);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
@@ -225,22 +241,31 @@ class EmailListRecordView extends ListRecordView {
|
||||
Espo.Ui.notify(false);
|
||||
|
||||
if (result.id) {
|
||||
helper
|
||||
.process(result.id, 'moveToFolder')
|
||||
helper.process(result.id, 'moveToFolder')
|
||||
.then(view => {
|
||||
this.listenToOnce(view, 'close:success', () => {
|
||||
this.collection.fetch().then(() => {
|
||||
Espo.Ui.success(this.translate('Done'));
|
||||
});
|
||||
this.collection.fetch()
|
||||
.then(() => Espo.Ui.success(this.translate('Done')));
|
||||
});
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.collection.fetch().then(() => {
|
||||
Espo.Ui.success(this.translate('Done'));
|
||||
});
|
||||
if (folderId === 'archive') {
|
||||
[...this.checkedList].forEach(id => {
|
||||
this.collection.trigger('moving-to-archive', id, this.collection.get(id));
|
||||
|
||||
this.uncheckRecord(id, null, true);
|
||||
});
|
||||
|
||||
Espo.Ui.info(this.translate('Moved to Archive', 'labels', 'Email'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.collection.fetch()
|
||||
.then(() => Espo.Ui.success(this.translate('Done')));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -259,6 +284,11 @@ class EmailListRecordView extends ListRecordView {
|
||||
});
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
massActionMoveToArchive() {
|
||||
this.massMoveToFolder('archive');
|
||||
}
|
||||
|
||||
actionMarkAsImportant(data) {
|
||||
data = data || {};
|
||||
|
||||
@@ -395,9 +425,16 @@ class EmailListRecordView extends ListRecordView {
|
||||
|
||||
this.moveToFolder(id, folderId)
|
||||
.then(() => {
|
||||
this.collection.fetch().then(() => {
|
||||
Espo.Ui.success(this.translate('Done'));
|
||||
});
|
||||
if (folderId === 'archive') {
|
||||
this.collection.trigger('moving-to-archive', id, this.collection.get(id));
|
||||
|
||||
Espo.Ui.info(this.translate('Moved to Archive', 'labels', 'Email'));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
this.collection.fetch()
|
||||
.then(() => Espo.Ui.success(this.translate('Done')));
|
||||
});
|
||||
|
||||
return;
|
||||
@@ -423,6 +460,7 @@ class EmailListRecordView extends ListRecordView {
|
||||
});
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
/**
|
||||
* @private
|
||||
* @param {{id: string}} data
|
||||
|
||||
Reference in New Issue
Block a user