diff --git a/client/res/templates/email-folder/list-side.tpl b/client/res/templates/email-folder/list-side.tpl index 975e809ea4..3abeefd830 100644 --- a/client/res/templates/email-folder/list-side.tpl +++ b/client/res/templates/email-folder/list-side.tpl @@ -1,5 +1,4 @@ - - diff --git a/client/src/views/email/list.js b/client/src/views/email/list.js index 2556d6af81..bbf72fd6be 100644 --- a/client/src/views/email/list.js +++ b/client/src/views/email/list.js @@ -26,9 +26,15 @@ * these Appropriate Legal Notices must retain the display of the "EspoCRM" word. ************************************************************************/ -define('views/email/list', 'views/list', function (Dep) { +define('views/email/list', ['views/list'], function (Dep) { - return Dep.extend({ + /** + * @class + * @name Class + * @memberOf module:views/email/list + * @extends module:views/list.Class + */ + return Dep.extend(/** @lends module:views/email/list.Class# */{ createButton: false, @@ -44,6 +50,78 @@ define('views/email/list', 'views/list', function (Dep) { keepCurrentRootUrl: true, + /** @const */ + FOLDER_ALL: 'all', + /** @const */ + FOLDER_INBOX: 'inbox', + /** @const */ + FOLDER_IMPORTANT: 'important', + /** @const */ + FOLDER_SENT: 'sent', + /** @const */ + FOLDER_DRAFTS: 'drafts', + /** @const */ + FOLDER_TRASH: 'trash', + + noDropFolderIdList: [ + 'all', + 'sent', + 'drafts', + ], + + events: { + 'mousedown .folders-container + .list-container a.link': function (e) { + $(e.target).attr('draggable', 'true'); + }, + 'dragstart a.link': function (e) { + let $target = $(e.target); + let id = $target.attr('data-id'); + + e.originalEvent.dataTransfer.dropEffect = 'move'; + e.originalEvent.dataTransfer.effectAllowed = 'move'; + + e.originalEvent.dataTransfer.setData('text/plain', id); + }, + 'dragenter .folder-list > li.droppable': function (e) { + if (this.selectedFolderId === this.FOLDER_ALL) { + return; + } + + let $target = $(e.target); + + $target.addClass('active'); + $target.find('a').css('pointer-events', 'none'); + }, + 'dragleave .folder-list > li.droppable': function (e) { + if (this.selectedFolderId === this.FOLDER_ALL) { + return; + } + + let $target = $(e.target); + + $target.removeClass('active') + $target.find('a').css('pointer-events', ''); + }, + 'drop .folder-list > li.droppable': function (e) { + if (this.selectedFolderId === this.FOLDER_ALL) { + return; + } + + let $target = $(e.target); + let folderId = $target.attr('data-id'); + let id = e.originalEvent.dataTransfer.getData('text/plain'); + + $target.removeClass('active'); + $target.find('a').css('pointer-events', ''); + + this.onDrop(id, folderId); + }, + 'dragover .folder-list > li.droppable': function (e) { + e.preventDefault(); + }, + ...Dep.prototype.events, + }, + setup: function () { Dep.prototype.setup.call(this); @@ -140,7 +218,13 @@ define('views/email/list', 'views/list', function (Dep) { loadFolders: function () { var xhr = null; - this.getFolderCollection((collection) => { + this.getFolderCollection(collection => { + collection.forEach(model => { + if (this.noDropFolderIdList.indexOf(model.id) === -1) { + model.droppable = true; + } + }); + this.createView('folders', 'views/email-folder/list-side', { collection: collection, emailCollection: this.collection, @@ -216,6 +300,46 @@ define('views/email/list', 'views/list', function (Dep) { } }, + onDrop: function (id, folderId) { + if (folderId === this.FOLDER_IMPORTANT) { + this.getRecordView().actionMarkAsImportant({id: id}); + + return; + } + + if (this.selectedFolderId === this.FOLDER_TRASH) { + if (folderId === this.FOLDER_TRASH) { + return; + } + + if (folderId === this.FOLDER_INBOX) { + this.getRecordView().actionRetrieveFromTrash({id: id}); + + return; + } + + this.getRecordView().actionRetrieveFromTrashMoveToFolder({id: id, folderId: folderId}); + + return; + } + + if (folderId === this.FOLDER_TRASH) { + this.getRecordView().actionMoveToTrash({id: id}); + + return; + } + + this.getRecordView().actionMoveToFolder({id: id, folderId: folderId}); + }, + + /** + * @protected + * @return {module:views/email/record/list.Class} + */ + getRecordView: function () { + return this.getView('list'); + }, + /** * @protected * @param {JQueryKeyEventObject} e diff --git a/client/src/views/email/record/list.js b/client/src/views/email/record/list.js index ed5fb64ed2..ea7f96b6af 100644 --- a/client/src/views/email/record/list.js +++ b/client/src/views/email/record/list.js @@ -28,7 +28,13 @@ define('views/email/record/list', ['views/record/list', 'helpers/mass-action'], function (Dep, MassActionHelper) { - return Dep.extend({ + /** + * @class + * @name Class + * @memberOf module:views/email/record/list + * @extends module:views/record/list.Class + */ + return Dep.extend(/** @lends module:views/email/record/list.Class# */{ rowActionsView: 'views/email/record/row-actions/default', @@ -309,7 +315,9 @@ define('views/email/record/list', ['views/record/list', 'helpers/mass-action'], }, actionMoveToTrash: function (data) { - var id = data.id; + let id = data.id; + + Espo.Ui.notify(' ... '); Espo.Ajax .postRequest('Email/action/moveToTrash', { @@ -323,12 +331,11 @@ define('views/email/record/list', ['views/record/list', 'helpers/mass-action'], }, actionRetrieveFromTrash: function (data) { - var id = data.id; + let id = data.id; - Espo.Ajax - .postRequest('Email/action/retrieveFromTrash', { - id: id - }) + Espo.Ui.notify(' ... '); + + this.retrieveFromTrash(id) .then(() => { Espo.Ui.warning(this.translate('Retrieved from Trash', 'labels', 'Email')); @@ -336,8 +343,60 @@ define('views/email/record/list', ['views/record/list', 'helpers/mass-action'], }); }, + /** + * @param {string} id + * @return {Promise} + */ + retrieveFromTrash: function (id) { + return Espo.Ajax.postRequest('Email/action/retrieveFromTrash', {id: id}); + }, + + actionRetrieveFromTrashMoveToFolder: function (data) { + let id = data.id; + let folderId = data.folderId; + + Espo.Ui.notify(' ... '); + + this.retrieveFromTrash(id) + .then(() => { + return this.moveToFolder(id, folderId) + }) + .then(() => { + this.collection.fetch().then(() => { + Espo.Ui.success(this.translate('Done')); + }); + }); + }, + + /** + * @param {string} id + * @param {string} folderId + * @return {Promise} + */ + moveToFolder: function (id, folderId) { + return Espo.Ajax + .postRequest('Email/action/moveToFolder', { + id: id, + folderId: folderId, + }); + }, + actionMoveToFolder: function (data) { - var id = data.id; + let id = data.id; + let folderId = data.folderId; + + if (folderId) { + Espo.Ui.notify(' ... '); + + this.moveToFolder(id, folderId) + .then(() => { + this.collection.fetch().then(() => { + Espo.Ui.success(this.translate('Done')); + }); + }); + + return; + } this.createView('dialog', 'views/email-folder/modals/select-folder', {}, view => { view.render(); @@ -345,11 +404,9 @@ define('views/email/record/list', ['views/record/list', 'helpers/mass-action'], this.listenToOnce(view, 'select', folderId => { this.clearView('dialog'); - Espo.Ajax - .postRequest('Email/action/moveToFolder', { - id: id, - folderId: folderId - }) + Espo.Ui.notify(' ... '); + + this.moveToFolder(id, folderId) .then(() => { this.collection.fetch().then(() => { Espo.Ui.success(this.translate('Done')); diff --git a/frontend/less/espo/custom.less b/frontend/less/espo/custom.less index e3f2b11a3c..a5fd794967 100644 --- a/frontend/less/espo/custom.less +++ b/frontend/less/espo/custom.less @@ -984,6 +984,19 @@ input.global-search-input { } } +.list-group { + .list-group-item { + &.droppable.active { + background-color: var(--state-warning-bg); + } + } +} + +.list-group-side { + > li.droppable.active { + border-left-color: var(--brand-warning); + } +} .list-group-item { margin-bottom: 0;