email move impr
This commit is contained in:
@@ -141,8 +141,16 @@ class InFolder implements ItemConverter
|
||||
$this->joinEmailUser($queryBuilder);
|
||||
|
||||
return WhereClause::fromRaw([
|
||||
Email::ALIAS_INBOX . '.userId' => $this->user->getId(),
|
||||
Email::ALIAS_INBOX . '.inTrash' => true,
|
||||
'OR' => [
|
||||
[
|
||||
Email::ALIAS_INBOX . '.userId' => $this->user->getId(),
|
||||
Email::ALIAS_INBOX . '.inTrash' => true,
|
||||
],
|
||||
[
|
||||
'groupFolderId!=' => null,
|
||||
'groupStatusFolder' => Email::GROUP_STATUS_FOLDER_TRASH,
|
||||
],
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -151,8 +159,16 @@ class InFolder implements ItemConverter
|
||||
$this->joinEmailUser($queryBuilder);
|
||||
|
||||
return WhereClause::fromRaw([
|
||||
Email::ALIAS_INBOX . '.userId' => $this->user->getId(),
|
||||
Email::ALIAS_INBOX . '.inArchive' => true,
|
||||
'OR' => [
|
||||
[
|
||||
Email::ALIAS_INBOX . '.userId' => $this->user->getId(),
|
||||
Email::ALIAS_INBOX . '.inArchive' => true,
|
||||
],
|
||||
[
|
||||
'groupFolderId!=' => null,
|
||||
'groupStatusFolder' => Email::GROUP_STATUS_FOLDER_ARCHIVE,
|
||||
],
|
||||
]
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -177,11 +193,7 @@ class InFolder implements ItemConverter
|
||||
|
||||
return WhereClause::fromRaw([
|
||||
'groupFolderId' => $groupFolderId,
|
||||
'OR' => [
|
||||
Email::ALIAS_INBOX . '.id' => null,
|
||||
Email::ALIAS_INBOX . '.inTrash' => false,
|
||||
Email::ALIAS_INBOX . '.inArchive' => false,
|
||||
]
|
||||
'groupStatusFolder' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -60,6 +60,9 @@ class Email extends Entity
|
||||
public const USERS_COLUMN_FOLDER_ID = 'folderId';
|
||||
public const USERS_COLUMN_IS_IMPORTANT = 'isImportant';
|
||||
|
||||
public const GROUP_STATUS_FOLDER_ARCHIVE = 'Archive';
|
||||
public const GROUP_STATUS_FOLDER_TRASH = 'Trash';
|
||||
|
||||
/** @noinspection PhpUnused */
|
||||
protected function _getSubject(): ?string
|
||||
{
|
||||
@@ -727,6 +730,18 @@ class Email extends Entity
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function getGroupStatusFolder(): ?string
|
||||
{
|
||||
return $this->get('groupStatusFolder');
|
||||
}
|
||||
|
||||
public function setGroupStatusFolder(?string $groupStatusFolder): self
|
||||
{
|
||||
$this->set('groupStatusFolder', $groupStatusFolder);
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
public function setDateSent(?DateTime $dateSent): self
|
||||
{
|
||||
$this->setValueObject('dateSent', $dateSent);
|
||||
|
||||
@@ -59,7 +59,8 @@
|
||||
"createdEvent": "Created Event",
|
||||
"event": "Event",
|
||||
"icsEventDateStart": "ICS Event Date Start",
|
||||
"groupFolder": "Group Folder"
|
||||
"groupFolder": "Group Folder",
|
||||
"groupStatusFolder": "Group Status Folder"
|
||||
},
|
||||
"links": {
|
||||
"replied": "Replied",
|
||||
@@ -85,6 +86,10 @@
|
||||
"Archived": "Imported",
|
||||
"Received": "Received",
|
||||
"Failed": "Failed"
|
||||
},
|
||||
"groupStatusFolder": {
|
||||
"Archive": "Archive",
|
||||
"Trash": "Trash"
|
||||
}
|
||||
},
|
||||
"labels": {
|
||||
@@ -126,7 +131,8 @@
|
||||
"Retrieved from Trash": "Retrieved from Trash"
|
||||
},
|
||||
"strings": {
|
||||
"sendingFailed": "Email sending failed"
|
||||
"sendingFailed": "Email sending failed",
|
||||
"group": "Group"
|
||||
},
|
||||
"messages": {
|
||||
"alreadyImported": "The [email]({link}) already exists in the system.",
|
||||
|
||||
@@ -150,13 +150,28 @@
|
||||
"visible": {
|
||||
"conditionGroup": [
|
||||
{
|
||||
"type": "isTrue",
|
||||
"attribute": "isUsers"
|
||||
},
|
||||
{
|
||||
"type": "isFalse",
|
||||
"attribute": "isUsersSent"
|
||||
"type": "or",
|
||||
"value": [
|
||||
{
|
||||
"type": "and",
|
||||
"value": [
|
||||
{
|
||||
"type": "isTrue",
|
||||
"attribute": "isUsers"
|
||||
},
|
||||
{
|
||||
"type": "isFalse",
|
||||
"attribute": "isUsersSent"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"type": "isNotEmpty",
|
||||
"attribute": "groupFolderId"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -585,6 +585,18 @@
|
||||
"groupFolder": {
|
||||
"type": "link",
|
||||
"massUpdateDisabled": true
|
||||
},
|
||||
"groupStatusFolder": {
|
||||
"type": "enum",
|
||||
"options": [
|
||||
"",
|
||||
"Archive",
|
||||
"Trash"
|
||||
],
|
||||
"maxLength": 7,
|
||||
"readOnly": true,
|
||||
"customizationDisabled": true,
|
||||
"index": true
|
||||
}
|
||||
},
|
||||
"links": {
|
||||
|
||||
@@ -35,7 +35,8 @@
|
||||
"sentById",
|
||||
"replyToString",
|
||||
"hasAttachment",
|
||||
"groupFolderId"
|
||||
"groupFolderId",
|
||||
"groupStatusFolder"
|
||||
],
|
||||
"beforeReadHookClassNameList": [
|
||||
"Espo\\Classes\\RecordHooks\\Email\\MarkAsRead"
|
||||
|
||||
@@ -84,33 +84,20 @@ class InboxService
|
||||
$folderId = null;
|
||||
}
|
||||
|
||||
$email = $this->entityManager->getRDBRepositoryByClass(Email::class)->getById($id);
|
||||
$email = $this->getEmail($id);
|
||||
$user = $this->getUser($userId);
|
||||
|
||||
if (!$email) {
|
||||
throw new NotFound();
|
||||
}
|
||||
$prevGroupFolderLink = $email->getGroupFolder();
|
||||
|
||||
$user = $userId === $this->user->getId() ?
|
||||
$this->user :
|
||||
$this->entityManager
|
||||
->getRDBRepositoryByClass(User::class)
|
||||
->getById($userId);
|
||||
|
||||
if (!$user) {
|
||||
throw new NotFound("User not found.");
|
||||
}
|
||||
|
||||
$previousFolderLink = $email->getGroupFolder();
|
||||
|
||||
if ($previousFolderLink) {
|
||||
$this->checkCurrentGroupFolder($previousFolderLink->getId(), $user);
|
||||
if ($prevGroupFolderLink) {
|
||||
$this->checkCurrentGroupFolder($prevGroupFolderLink->getId(), $user);
|
||||
}
|
||||
|
||||
if ($folderId && str_starts_with($folderId, 'group:')) {
|
||||
try {
|
||||
$this->moveToGroupFolder($email, substr($folderId, 6), $user);
|
||||
} catch (Exception $e) {
|
||||
$this->log->debug("Could not move email to group folder. " . $e->getMessage());
|
||||
$this->log->debug("Could not move email to group folder. {message}", ['message' => $e->getMessage()]);
|
||||
|
||||
throw $e;
|
||||
}
|
||||
@@ -124,13 +111,15 @@ class InboxService
|
||||
return;
|
||||
}
|
||||
|
||||
if ($previousFolderLink) {
|
||||
$email->setGroupFolderId(null);
|
||||
|
||||
if (!$this->aclManager->checkEntityRead($user, $email)) {
|
||||
throw new Forbidden("No read access to email to unset group folder.");
|
||||
if ($prevGroupFolderLink) {
|
||||
if (!$this->aclManager->checkEntityEdit($user, $email)) {
|
||||
throw new Forbidden("Cannot unset group folder. No edit access to email.");
|
||||
}
|
||||
|
||||
$email
|
||||
->setGroupFolderId(null)
|
||||
->setGroupStatusFolder(null);
|
||||
|
||||
$this->entityManager->saveEntity($email);
|
||||
}
|
||||
|
||||
@@ -159,25 +148,31 @@ class InboxService
|
||||
*/
|
||||
private function moveToGroupFolder(Email $email, string $folderId, User $user): void
|
||||
{
|
||||
$folder = $this->entityManager->getEntityById(GroupEmailFolder::ENTITY_TYPE, $folderId);
|
||||
|
||||
if (!$folder) {
|
||||
throw new NotFound("Group folder not found.");
|
||||
}
|
||||
$folder = $this->getGroupFolder($folderId);
|
||||
|
||||
if (!$this->aclManager->checkEntityRead($user, $folder)) {
|
||||
throw new Forbidden("No access to folder.");
|
||||
throw new Forbidden("Cannot move to group folder. No access to folder.");
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkEntityRead($user, $email)) {
|
||||
throw new Forbidden("No read access to email to unset group folder.");
|
||||
throw new Forbidden("Cannot move to group folder. No read access to email.");
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkField($user, Email::ENTITY_TYPE, 'groupFolder', Table::ACTION_EDIT)) {
|
||||
throw new Forbidden("No access to `groupFolder` field.");
|
||||
throw new Forbidden("Cannot move to group folder. No edit access to `groupFolder` field.");
|
||||
}
|
||||
|
||||
$email->setGroupFolderId($folderId);
|
||||
if (
|
||||
!$email->getGroupFolder() &&
|
||||
!$this->aclManager->checkEntityEdit($user, $email)
|
||||
) {
|
||||
throw new Forbidden("Cannot move to group folder from All folder. No edit access to email.");
|
||||
}
|
||||
|
||||
$email
|
||||
->setGroupFolderId($folderId)
|
||||
->setGroupStatusFolder(null);
|
||||
|
||||
$this->entityManager->saveEntity($email);
|
||||
|
||||
$this->retrieveFromArchive($email, $user);
|
||||
@@ -189,7 +184,9 @@ class InboxService
|
||||
public function moveToTrashIdList(array $idList, ?string $userId = null): bool
|
||||
{
|
||||
foreach ($idList as $id) {
|
||||
$this->moveToTrash($id, $userId);
|
||||
try {
|
||||
$this->moveToTrash($id, $userId);
|
||||
} catch (Exception) {}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -201,14 +198,41 @@ class InboxService
|
||||
public function retrieveFromTrashIdList(array $idList, ?string $userId = null): void
|
||||
{
|
||||
foreach ($idList as $id) {
|
||||
$this->retrieveFromTrash($id, $userId);
|
||||
try {
|
||||
$this->retrieveFromTrash($id, $userId);
|
||||
} catch (Exception) {}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFound
|
||||
* @throws Forbidden
|
||||
*/
|
||||
public function moveToTrash(string $id, ?string $userId = null): void
|
||||
{
|
||||
$userId = $userId ?? $this->user->getId();
|
||||
|
||||
$email = $this->getEmail($id);
|
||||
$user = $this->getUser($userId);
|
||||
|
||||
if ($email->getGroupFolder()) {
|
||||
$folder = $this->getGroupFolder($email->getGroupFolder()->getId());
|
||||
|
||||
if (!$this->aclManager->checkEntityRead($user, $email)) {
|
||||
throw new Forbidden("Cannot move email from group folder to trash. No access to email.");
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkEntityRead($user, $folder)) {
|
||||
throw new Forbidden("Cannot move email from group folder to trash. No access to group folder.");
|
||||
}
|
||||
|
||||
$email->setGroupStatusFolder(Email::GROUP_STATUS_FOLDER_TRASH);
|
||||
|
||||
$this->entityManager->saveEntity($email);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$update = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->update()
|
||||
@@ -226,10 +250,35 @@ class InboxService
|
||||
$this->markNotificationAsRead($id, $userId);
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws Forbidden
|
||||
* @throws NotFound
|
||||
*/
|
||||
public function retrieveFromTrash(string $id, ?string $userId = null): void
|
||||
{
|
||||
$userId = $userId ?? $this->user->getId();
|
||||
|
||||
$email = $this->getEmail($id);
|
||||
$user = $this->getUser($userId);
|
||||
|
||||
if ($email->getGroupFolder()) {
|
||||
$folder = $this->getGroupFolder($email->getGroupFolder()->getId());
|
||||
|
||||
if (!$this->aclManager->checkEntityRead($user, $email)) {
|
||||
throw new Forbidden("Cannot retrieve group folder email from trash. No access to email.");
|
||||
}
|
||||
|
||||
if (!$this->aclManager->checkEntityRead($user, $folder)) {
|
||||
throw new Forbidden("Cannot retrieve group folder email from trash. No access to group folder.");
|
||||
}
|
||||
|
||||
$email->setGroupStatusFolder(null);
|
||||
|
||||
$this->entityManager->saveEntity($email);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$update = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->update()
|
||||
@@ -519,6 +568,14 @@ class InboxService
|
||||
throw new Forbidden("No 'read' access");
|
||||
}
|
||||
|
||||
if ($email->getGroupFolder()) {
|
||||
$email->setGroupStatusFolder(Email::GROUP_STATUS_FOLDER_ARCHIVE);
|
||||
|
||||
$this->entityManager->saveEntity($email);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$update = $this->entityManager
|
||||
->getQueryBuilder()
|
||||
->update()
|
||||
@@ -573,4 +630,48 @@ class InboxService
|
||||
throw new Forbidden("No access to `groupFolder` field.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFound
|
||||
*/
|
||||
private function getUser(string $userId): User
|
||||
{
|
||||
$user = $userId === $this->user->getId() ?
|
||||
$this->user :
|
||||
$this->entityManager->getRDBRepositoryByClass(User::class)->getById($userId);
|
||||
|
||||
if (!$user) {
|
||||
throw new NotFound("User not found.");
|
||||
}
|
||||
|
||||
return $user;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFound
|
||||
*/
|
||||
private function getEmail(string $id): Email
|
||||
{
|
||||
$email = $this->entityManager->getRDBRepositoryByClass(Email::class)->getById($id);
|
||||
|
||||
if (!$email) {
|
||||
throw new NotFound();
|
||||
}
|
||||
|
||||
return $email;
|
||||
}
|
||||
|
||||
/**
|
||||
* @throws NotFound
|
||||
*/
|
||||
private function getGroupFolder(string $folderId): GroupEmailFolder
|
||||
{
|
||||
$folder = $this->entityManager->getRDBRepositoryByClass(GroupEmailFolder::class)->getById($folderId);
|
||||
|
||||
if (!$folder) {
|
||||
throw new NotFound("Group folder not found.");
|
||||
}
|
||||
|
||||
return $folder;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,7 +33,6 @@ export default class extends ModalView {
|
||||
template = 'email-folder/modals/select-folder'
|
||||
|
||||
cssName = 'select-folder'
|
||||
fitHeight = true
|
||||
backdrop = true
|
||||
|
||||
data() {
|
||||
@@ -52,6 +51,8 @@ export default class extends ModalView {
|
||||
});
|
||||
|
||||
this.headerText = this.options.headerText || '';
|
||||
this.isGroup = this.options.isGroup || false;
|
||||
this.noArchive = this.options.noArchive || false;
|
||||
|
||||
if (this.headerText === '') {
|
||||
this.buttonList.push({
|
||||
@@ -64,19 +65,25 @@ export default class extends ModalView {
|
||||
|
||||
this.wait(
|
||||
Espo.Ajax.getRequest('EmailFolder/action/listAll')
|
||||
.then(data => {
|
||||
.then(/** {list: {id: string, name: string}[]} */data => {
|
||||
Espo.Ui.notify(false);
|
||||
|
||||
const builtInFolders = [
|
||||
'inbox',
|
||||
'important',
|
||||
'sent',
|
||||
'drafts',
|
||||
'trash',
|
||||
'archive',
|
||||
];
|
||||
|
||||
this.folderDataList = data.list
|
||||
.filter(item => {
|
||||
return [
|
||||
'inbox',
|
||||
'important',
|
||||
'sent',
|
||||
'drafts',
|
||||
'trash',
|
||||
'archive',
|
||||
].indexOf(item.id) === -1;
|
||||
if (this.isGroup && !item.id.startsWith('group:')) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return !builtInFolders.includes(item.id);
|
||||
})
|
||||
.map(item => {
|
||||
return {
|
||||
@@ -88,13 +95,18 @@ export default class extends ModalView {
|
||||
|
||||
this.folderDataList.unshift({
|
||||
id: 'inbox',
|
||||
name: this.translate('inbox', 'presetFilters', 'Email'),
|
||||
name: this.isGroup ?
|
||||
this.translate('all', 'presetFilters', 'Email') :
|
||||
this.translate('inbox', 'presetFilters', 'Email'),
|
||||
});
|
||||
|
||||
this.folderDataList.push({
|
||||
id: 'archive',
|
||||
name: this.translate('archive', 'presetFilters', 'Email'),
|
||||
});
|
||||
|
||||
if (!this.noArchive) {
|
||||
this.folderDataList.push({
|
||||
id: 'archive',
|
||||
name: this.translate('archive', 'presetFilters', 'Email'),
|
||||
});
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
|
||||
@@ -112,19 +112,11 @@ class EmailDetailView extends DetailView {
|
||||
}
|
||||
}
|
||||
|
||||
this.listenTo(this.model, 'change', () => {
|
||||
this.listenTo(this.model, 'change:isImportant change:inTrash change:inArchive change:groupStatusFolder', () => {
|
||||
if (!this.isRendered()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
!this.model.hasChanged('isImportant') &&
|
||||
!this.model.hasChanged('inTrash') &&
|
||||
!this.model.hasChanged('inArchive')
|
||||
) {
|
||||
return;
|
||||
}
|
||||
|
||||
const headerView = this.getHeaderView();
|
||||
|
||||
if (headerView) {
|
||||
@@ -559,9 +551,15 @@ class EmailDetailView extends DetailView {
|
||||
getHeader() {
|
||||
const name = this.model.get('name');
|
||||
|
||||
const isImportant = this.model.get('isImportant');
|
||||
const inTrash = this.model.get('inTrash');
|
||||
const inArchive = this.model.get('inArchive');
|
||||
const isImportant = this.model.attributes.isImportant;
|
||||
|
||||
const inTrash = this.model.attributes.groupFolderId ?
|
||||
this.model.attributes.groupStatusFolder === 'Trash' :
|
||||
this.model.attributes.inTrash;
|
||||
|
||||
const inArchive = this.model.attributes.groupFolderId ?
|
||||
this.model.attributes.groupStatusFolder === 'Archive' :
|
||||
this.model.attributes.inArchive;
|
||||
|
||||
const rootUrl = this.options.rootUrl || this.options.params.rootUrl || '#' + this.scope;
|
||||
|
||||
|
||||
@@ -45,6 +45,7 @@ class EmailFolderStringFieldView extends BaseFieldView {
|
||||
|
||||
// noinspection JSCheckFunctionSignatures
|
||||
data() {
|
||||
console.log(this.getFolderString());
|
||||
if (!this.model.has('folderId')) {
|
||||
return {valueIsSet: false};
|
||||
}
|
||||
@@ -57,6 +58,7 @@ class EmailFolderStringFieldView extends BaseFieldView {
|
||||
|
||||
getAttributeList() {
|
||||
return [
|
||||
'isUsers',
|
||||
'folderId',
|
||||
'folderName',
|
||||
'groupFolderId',
|
||||
@@ -64,6 +66,7 @@ class EmailFolderStringFieldView extends BaseFieldView {
|
||||
'inArchive',
|
||||
'inTrash',
|
||||
'isUsersSent',
|
||||
'groupStatusFolder',
|
||||
];
|
||||
}
|
||||
|
||||
@@ -83,12 +86,20 @@ class EmailFolderStringFieldView extends BaseFieldView {
|
||||
return this.translate('archive', 'presetFilters', 'Email');
|
||||
}
|
||||
|
||||
if (this.model.get('folderName')) {
|
||||
return this.model.get('folderName');
|
||||
if (this.model.attributes.folderName && this.model.attributes.folderId) {
|
||||
return this.model.attributes.folderName;
|
||||
}
|
||||
|
||||
if (this.model.get('groupFolderName')) {
|
||||
return this.model.get('groupFolderName');
|
||||
let string = this.translate('group', 'strings', 'Email') + ' · ' + this.model.get('groupFolderName');
|
||||
|
||||
if (this.model.attributes.groupStatusFolder === 'Archive') {
|
||||
string += ' · ' + this.translate('archive', 'presetFilters', 'Email');
|
||||
} else if (this.model.attributes.groupStatusFolder === 'Trash') {
|
||||
string += ' · ' + this.translate('trash', 'presetFilters', 'Email');
|
||||
}
|
||||
|
||||
return string;
|
||||
}
|
||||
|
||||
if (this.model.get('isUsers')) {
|
||||
|
||||
@@ -39,7 +39,14 @@ class EmailSubjectFieldView extends VarcharFieldView {
|
||||
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.inTrash = this.model.attributes.groupFolderId ?
|
||||
this.model.attributes.groupStatusFolder === 'Trash' :
|
||||
this.model.attributes.inTrash;
|
||||
|
||||
data.inArchive = this.model.attributes.groupFolderId ?
|
||||
this.model.attributes.groupStatusFolder === 'Archive' :
|
||||
this.model.attributes.inArchive;
|
||||
|
||||
if (!data.isRead && !this.model.has('isRead')) {
|
||||
data.isRead = true;
|
||||
@@ -63,7 +70,15 @@ class EmailSubjectFieldView extends VarcharFieldView {
|
||||
}
|
||||
|
||||
getAttributeList() {
|
||||
return ['name', 'subject', 'isRead', 'isImportant', 'hasAttachment', 'inTrash'];
|
||||
return [
|
||||
'name',
|
||||
'subject',
|
||||
'isRead',
|
||||
'isImportant',
|
||||
'hasAttachment',
|
||||
'inTrash',
|
||||
'groupStatusFolder',
|
||||
];
|
||||
}
|
||||
|
||||
setup() {
|
||||
@@ -75,11 +90,9 @@ class EmailSubjectFieldView extends VarcharFieldView {
|
||||
this.showAttachments();
|
||||
}
|
||||
|
||||
this.listenTo(this.model, 'change', () => {
|
||||
this.listenTo(this.model, 'change:isRead change:isImportant change:groupStatusFolder', () => {
|
||||
if (this.mode === this.MODE_LIST || this.mode === this.MODE_LIST_LINK) {
|
||||
if (this.model.hasChanged('isRead') || this.model.hasChanged('isImportant')) {
|
||||
this.reRender();
|
||||
}
|
||||
this.reRender();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -236,6 +236,17 @@ class EmailListView extends ListView {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.selectedFolderId.indexOf('group:') === 0) {
|
||||
if (
|
||||
[this.FOLDER_ALL, this.FOLDER_ARCHIVE, this.FOLDER_TRASH].includes(folderId) ||
|
||||
folderId.startsWith('group:')
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.model.get('isUsers')) {
|
||||
if (this.model.attributes.isUsers) {
|
||||
this.addDropdownItem({
|
||||
label: 'Mark as Important',
|
||||
name: 'markAsImportant',
|
||||
@@ -145,14 +145,14 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
this.addDropdownItem({
|
||||
label: 'Move to Trash',
|
||||
name: 'moveToTrash',
|
||||
hidden: this.model.get('inTrash'),
|
||||
hidden: this.isInTrash(),
|
||||
groupIndex: 2,
|
||||
});
|
||||
|
||||
this.addDropdownItem({
|
||||
label: 'Retrieve from Trash',
|
||||
name: 'retrieveFromTrash',
|
||||
hidden: !this.model.get('inTrash'),
|
||||
hidden: !this.isInTrash(),
|
||||
groupIndex: 2,
|
||||
});
|
||||
|
||||
@@ -160,10 +160,45 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
labelTranslation: 'Email.actions.moveToArchive',
|
||||
name: 'moveToArchive',
|
||||
groupIndex: 2,
|
||||
hidden: this.model.get('inArchive'),
|
||||
hidden: this.isInArchive(),
|
||||
onClick: () => this.actionMoveToArchive(),
|
||||
});
|
||||
|
||||
this.addDropdownItem({
|
||||
label: 'Move to Folder',
|
||||
name: 'moveToFolder',
|
||||
groupIndex: 2,
|
||||
});
|
||||
} else if (this.model.attributes.groupFolderId) {
|
||||
this.addDropdownItem({
|
||||
label: 'Move to Trash',
|
||||
name: 'moveToTrash',
|
||||
hidden: this.isInTrash(),
|
||||
groupIndex: 2,
|
||||
});
|
||||
|
||||
this.addDropdownItem({
|
||||
label: 'Retrieve from Trash',
|
||||
name: 'retrieveFromTrash',
|
||||
hidden: !this.isInTrash(),
|
||||
groupIndex: 2,
|
||||
});
|
||||
|
||||
this.addDropdownItem({
|
||||
labelTranslation: 'Email.actions.moveToArchive',
|
||||
name: 'moveToArchive',
|
||||
groupIndex: 2,
|
||||
hidden: this.isInArchive() || this.isInTrash(),
|
||||
onClick: () => this.actionMoveToArchive(),
|
||||
});
|
||||
|
||||
this.addDropdownItem({
|
||||
label: 'Move to Folder',
|
||||
name: 'moveToFolder',
|
||||
groupIndex: 2,
|
||||
hidden: this.isInTrash(),
|
||||
});
|
||||
} else {
|
||||
this.addDropdownItem({
|
||||
label: 'Move to Folder',
|
||||
name: 'moveToFolder',
|
||||
@@ -194,8 +229,8 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
}
|
||||
});
|
||||
|
||||
this.listenTo(this.model, 'change:inTrash', () => {
|
||||
if (this.model.get('inTrash')) {
|
||||
this.listenTo(this.model, 'change:inTrash change:groupStatusFolder', () => {
|
||||
if (this.isInTrash()) {
|
||||
this.hideActionItem('moveToTrash');
|
||||
this.showActionItem('retrieveFromTrash');
|
||||
} else {
|
||||
@@ -204,8 +239,8 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
}
|
||||
});
|
||||
|
||||
this.listenTo(this.model, 'change:inArchive', () => {
|
||||
if (this.model.get('inArchive')) {
|
||||
this.listenTo(this.model, 'change:inArchive change:groupStatusFolder', () => {
|
||||
if (this.isInArchive()) {
|
||||
this.hideActionItem('moveToArchive');
|
||||
} else {
|
||||
this.showActionItem('moveToArchive');
|
||||
@@ -297,7 +332,11 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
Espo.Ui.warning(this.translate('Moved to Trash', 'labels', 'Email'));
|
||||
});
|
||||
|
||||
this.model.set('inTrash', true);
|
||||
if (this.model.attributes.groupFolderId) {
|
||||
this.model.set('groupStatusFolder', 'Trash');
|
||||
} else {
|
||||
this.model.set('inTrash', true);
|
||||
}
|
||||
|
||||
if (this.model.collection) {
|
||||
this.model.collection.trigger('moving-to-trash', this.model.id, true);
|
||||
@@ -312,6 +351,10 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
|
||||
this.model.set('inTrash', false);
|
||||
|
||||
if (this.model.attributes.groupFolderId) {
|
||||
this.model.set('groupStatusFolder', null);
|
||||
}
|
||||
|
||||
if (this.model.collection) {
|
||||
this.model.collection.trigger('retrieving-from-trash', this.model.id, true);
|
||||
}
|
||||
@@ -320,22 +363,39 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
actionMoveToFolder() {
|
||||
this.createView('dialog', 'views/email-folder/modals/select-folder', {
|
||||
headerText: this.translate('Move to Folder', 'labels', 'Email'),
|
||||
}, (view) => {
|
||||
isGroup: !!this.model.attributes.groupFolderId || !this.model.attributes.isUsers,
|
||||
noArchive: !this.model.attributes.groupFolderId && !this.model.attributes.isUsers,
|
||||
}, view => {
|
||||
view.render();
|
||||
|
||||
this.listenToOnce(view, 'select', folderId => {
|
||||
this.listenToOnce(view, 'select', /** string|null */folderId => {
|
||||
this.clearView('dialog');
|
||||
|
||||
Espo.Ajax.postRequest(`Email/inbox/folders/${folderId}`, {id: this.model.id})
|
||||
.then(() => {
|
||||
this.model.set('inArchive', folderId === 'archive');
|
||||
if (this.model.attributes.groupFolderId) {
|
||||
if (folderId === 'archive') {
|
||||
this.model.set('groupStatusFolder', 'Archive');
|
||||
} else {
|
||||
this.model.set('groupStatusFolder', null);
|
||||
}
|
||||
} else {
|
||||
this.model.set('inArchive', folderId === 'archive');
|
||||
}
|
||||
|
||||
if (folderId === 'inbox' || folderId === 'archive') {
|
||||
folderId = null;
|
||||
}
|
||||
|
||||
if (!folderId) {
|
||||
this.model.set('groupFolderId', null);
|
||||
this.model.set('groupFolderName', null);
|
||||
}
|
||||
|
||||
this.model.set('folderId', folderId);
|
||||
|
||||
this.model.fetch();
|
||||
|
||||
Espo.Ui.success(this.translate('Done'));
|
||||
});
|
||||
});
|
||||
@@ -347,7 +407,9 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
|
||||
Espo.Ajax.postRequest(`Email/inbox/folders/archive`, {id: this.model.id})
|
||||
.then(() => {
|
||||
this.model.set('inArchive', true);
|
||||
this.model.attributes.groupFolderId ?
|
||||
this.model.set('groupStatusFolder', 'Archive') :
|
||||
this.model.set('inArchive', true);
|
||||
|
||||
Espo.Ui.info(this.translate('Moved to Archive', 'labels', 'Email'));
|
||||
|
||||
@@ -619,6 +681,26 @@ class EmailDetailRecordView extends DetailRecordView {
|
||||
|
||||
this.actionSaveAndContinueEditing();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @return {boolean}
|
||||
*/
|
||||
isInTrash() {
|
||||
return this.model.attributes.groupFolderId ?
|
||||
this.model.attributes.groupStatusFolder === 'Trash' :
|
||||
this.model.attributes.inTrash;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @return {boolean}
|
||||
*/
|
||||
isInArchive() {
|
||||
return this.model.attributes.groupFolderId ?
|
||||
this.model.attributes.groupStatusFolder === 'Archive' :
|
||||
this.model.attributes.inArchive;
|
||||
}
|
||||
}
|
||||
|
||||
export default EmailDetailRecordView;
|
||||
|
||||
@@ -74,7 +74,9 @@ class EmailListRecordView extends ListRecordView {
|
||||
const model = this.collection.get(id);
|
||||
|
||||
if (model) {
|
||||
model.set('inTrash', true);
|
||||
model.attributes.groupFolderId ?
|
||||
model.set('groupFolderStatus', 'Trash') :
|
||||
model.set('inTrash', true);
|
||||
}
|
||||
|
||||
if (this.rootData.selectedFolderId !== 'trash' && this.rootData.selectedFolderId !== 'all') {
|
||||
@@ -92,7 +94,9 @@ class EmailListRecordView extends ListRecordView {
|
||||
const model = this.collection.get(id);
|
||||
|
||||
if (model) {
|
||||
model.set('inTrash', false);
|
||||
model.attributes.groupFolderId ?
|
||||
model.set('groupFolderStatus', null) :
|
||||
model.set('inTrash', false);
|
||||
}
|
||||
|
||||
if (this.rootData.selectedFolderId === 'trash') {
|
||||
@@ -110,7 +114,9 @@ class EmailListRecordView extends ListRecordView {
|
||||
const model = this.collection.get(id);
|
||||
|
||||
if (model) {
|
||||
model.set('inArchive', true);
|
||||
model.attributes.groupFolderId ?
|
||||
model.set('groupFolderStatus', 'Archive') :
|
||||
model.set('inArchive', true);
|
||||
}
|
||||
|
||||
if (this.rootData.selectedFolderId !== 'archive') {
|
||||
@@ -307,10 +313,22 @@ class EmailListRecordView extends ListRecordView {
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @return {string|null|undefined}
|
||||
*/
|
||||
getSelectedFolderId() {
|
||||
return this.rootData.selectedFolderId;
|
||||
}
|
||||
|
||||
// noinspection JSUnusedGlobalSymbols
|
||||
massActionMoveToFolder() {
|
||||
const selectedFolderId = this.getSelectedFolderId();
|
||||
|
||||
this.createView('dialog', 'views/email-folder/modals/select-folder', {
|
||||
headerText: this.translate('Move to Folder', 'labels', 'Email'),
|
||||
isGroup: selectedFolderId && (selectedFolderId.startsWith('group:') || selectedFolderId === 'all'),
|
||||
noArchive: selectedFolderId === 'all',
|
||||
}, view => {
|
||||
view.render();
|
||||
|
||||
@@ -492,8 +510,16 @@ class EmailListRecordView extends ListRecordView {
|
||||
return;
|
||||
}
|
||||
|
||||
const model = this.collection.get(id);
|
||||
|
||||
if (!model) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.createView('dialog', 'views/email-folder/modals/select-folder', {
|
||||
headerText: this.translate('Move to Folder', 'labels', 'Email'),
|
||||
isGroup: !!model.attributes.groupFolderId || !model.attributes.isUsers,
|
||||
noArchive: !model.attributes.groupFolderId && !model.attributes.isUsers,
|
||||
}, view => {
|
||||
view.render();
|
||||
|
||||
|
||||
@@ -33,12 +33,8 @@ class EmailDefaultRowActionView extends DefaultRowActionsView {
|
||||
setup() {
|
||||
super.setup();
|
||||
|
||||
this.listenTo(this.model, 'change', (model) => {
|
||||
if (model.hasChanged('isImportant') || model.hasChanged('inTrash')) {
|
||||
setTimeout(() => {
|
||||
this.reRender();
|
||||
}, 10);
|
||||
}
|
||||
this.listenTo(this.model, 'change:isImportant change:inTrash change:groupStatusFolder', () => {
|
||||
setTimeout(() => this.reRender(), 10);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -55,7 +51,7 @@ class EmailDefaultRowActionView extends DefaultRowActionsView {
|
||||
|
||||
if (
|
||||
this.model.get('createdById') === this.getUser().id && this.model.get('status') === 'Draft' &&
|
||||
!this.model.get('inTrash')
|
||||
!this.model.attributes.inTrash
|
||||
) {
|
||||
list.push({
|
||||
action: 'send',
|
||||
@@ -103,7 +99,7 @@ class EmailDefaultRowActionView extends DefaultRowActionsView {
|
||||
}
|
||||
}
|
||||
|
||||
if (this.model.get('isUsers') && !this.model.get('isRead')) {
|
||||
if (this.model.attributes.isUsers && !this.model.attributes.isRead) {
|
||||
list.push({
|
||||
action: 'markAsRead',
|
||||
label: 'Mark Read',
|
||||
@@ -114,8 +110,19 @@ class EmailDefaultRowActionView extends DefaultRowActionsView {
|
||||
});
|
||||
}
|
||||
|
||||
if (this.model.get('isUsers') && this.model.get('status') !== 'Draft') {
|
||||
if (!this.model.get('inTrash')) {
|
||||
if (
|
||||
(this.model.attributes.isUsers && this.model.attributes.status !== 'Draft') ||
|
||||
this.model.attributes.groupFolderId
|
||||
) {
|
||||
const inTrash = this.model.attributes.groupFolderId ?
|
||||
this.model.attributes.groupStatusFolder === 'Trash' :
|
||||
this.model.attributes.inTrash;
|
||||
|
||||
const inArchive = this.model.attributes.groupFolderId ?
|
||||
this.model.attributes.groupStatusFolder === 'Archive' :
|
||||
this.model.attributes.inArchive;
|
||||
|
||||
if (!inTrash) {
|
||||
list.push({
|
||||
action: 'moveToTrash',
|
||||
label: 'Move to Trash',
|
||||
@@ -135,7 +142,7 @@ class EmailDefaultRowActionView extends DefaultRowActionsView {
|
||||
});
|
||||
}
|
||||
|
||||
if (!this.model.attributes.inArchive) {
|
||||
if (!inArchive) {
|
||||
list.push({
|
||||
action: 'moveToArchive',
|
||||
text: this.getLanguage().translatePath('Email.actions.moveToArchive'),
|
||||
@@ -145,9 +152,20 @@ class EmailDefaultRowActionView extends DefaultRowActionsView {
|
||||
groupIndex: 2,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (this.model.get('isUsers') && this.model.get('status') !== 'Draft') {
|
||||
list.push({
|
||||
action: 'moveToFolder',
|
||||
label: 'Move to Folder',
|
||||
data: {
|
||||
id: this.model.id
|
||||
},
|
||||
groupIndex: 2,
|
||||
});
|
||||
} else if (
|
||||
!this.model.attributes.isUsers &&
|
||||
!this.model.attributes.groupFolderId &&
|
||||
this.model.attributes.status === 'Archived'
|
||||
) {
|
||||
list.push({
|
||||
action: 'moveToFolder',
|
||||
label: 'Move to Folder',
|
||||
|
||||
Reference in New Issue
Block a user